summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-08-25 00:25:25 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-08-25 00:25:25 -0500
commit31ebb6568fd8557ba184b38481887e540cbf5647 (patch)
treec5c50929cee795292fae4827e4d6993c2eb2a7ba
parent5fdf839b35497b5470dc9e27e8503083f0b55266 (diff)
downloadtdelibs-31ebb656.tar.gz
tdelibs-31ebb656.zip
Add preliminary cryptographic card support to TDEHWLib
-rw-r--r--tdecore/tdehw/CMakeLists.txt10
-rw-r--r--tdecore/tdehw/tdecryptographiccarddevice.cpp296
-rw-r--r--tdecore/tdehw/tdecryptographiccarddevice.h82
-rw-r--r--tdecore/tdehw/tdecryptographiccarddevice_private.h59
-rw-r--r--tdecore/tdehw/tdehardwaredevices.cpp3
-rw-r--r--tdecore/tdehw/tdehardwaredevices.h1
6 files changed, 448 insertions, 3 deletions
diff --git a/tdecore/tdehw/CMakeLists.txt b/tdecore/tdehw/CMakeLists.txt
index f9354ecfb..229ecc2fd 100644
--- a/tdecore/tdehw/CMakeLists.txt
+++ b/tdecore/tdehw/CMakeLists.txt
@@ -56,6 +56,12 @@ if( WITH_CONSOLEKIT )
add_definitions( -DWITH_CONSOLEKIT )
endif( )
+if( WITH_PCSC )
+ add_definitions( -DWITH_PCSC )
+ list( APPEND TDEHW_CUSTOM_INCLUDE_DIRS ${PCSCLITE_INCLUDE_DIRS} )
+ list( APPEND TDEHW_CUSTOM_LIBRARIES ${PCSCLITE_LIBRARIES} )
+endif( )
+
if( WITH_NETWORK_MANAGER_BACKEND )
list( APPEND TDEHW_CUSTOM_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/networkbackends/network-manager )
list( APPEND TDEHW_CUSTOM_LIBRARIES network_manager_backend-static )
@@ -83,7 +89,7 @@ install( FILES tdehardwaredevices.h tdenetworkconnections.h tdegenericdevice.h
tdestoragedevice.h tdecpudevice.h tdebatterydevice.h tdemainspowerdevice.h
tdenetworkdevice.h tdebacklightdevice.h tdemonitordevice.h
tdesensordevice.h tderootsystemdevice.h tdeeventdevice.h tdeinputdevice.h
- tdehwcommontypes.h
+ tdecryptographiccarddevice.h tdehwcommontypes.h
DESTINATION ${INCLUDE_INSTALL_DIR} )
@@ -96,7 +102,7 @@ set( ${target}_SRCS
tdestoragedevice.cpp tdecpudevice.cpp tdebatterydevice.cpp
tdemainspowerdevice.cpp tdenetworkdevice.cpp tdebacklightdevice.cpp
tdemonitordevice.cpp tdesensordevice.cpp tderootsystemdevice.cpp
- tdeeventdevice.cpp tdeinputdevice.cpp
+ tdeeventdevice.cpp tdeinputdevice.cpp tdecryptographiccarddevice.cpp
)
tde_add_library( ${target} STATIC_PIC AUTOMOC
diff --git a/tdecore/tdehw/tdecryptographiccarddevice.cpp b/tdecore/tdehw/tdecryptographiccarddevice.cpp
new file mode 100644
index 000000000..9c827a1f6
--- /dev/null
+++ b/tdecore/tdehw/tdecryptographiccarddevice.cpp
@@ -0,0 +1,296 @@
+/* This file is part of the TDE libraries
+ Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "tdecryptographiccarddevice_private.h"
+#include "tdecryptographiccarddevice.h"
+
+#include <tqpixmap.h>
+#include <tqtimer.h>
+#include <ntqthread.h>
+#include <ntqeventloop.h>
+#include <ntqapplication.h>
+
+#include "tdeglobal.h"
+#include "tdelocale.h"
+
+#include "tdehardwaredevices.h"
+
+#include "config.h"
+
+// 1 second
+#define PCSC_POLL_TIMEOUT_S 1000
+
+/* FIXME
+ * This is incomplete
+ */
+static TQString pcsc_error_code_to_string(long errcode) {
+ if (errcode == SCARD_W_UNPOWERED_CARD) {
+ return i18n("card not powered on");
+ }
+ else if (errcode == SCARD_E_PROTO_MISMATCH) {
+ return i18n("protocol mismatch");
+ }
+ else {
+ return TQString::null;
+ }
+}
+
+CryptoCardDeviceWatcher::CryptoCardDeviceWatcher() {
+ m_readerStates = NULL;
+}
+
+CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() {
+ free(m_readerStates);
+}
+
+void CryptoCardDeviceWatcher::run() {
+#ifdef WITH_PCSC
+ bool first_loop;
+ unsigned int i;
+ long ret;
+
+ DWORD dword_readers;
+ LPSTR lpstring_readers = NULL;
+
+ TQStringList readers;
+
+ first_loop = true;
+ m_terminationRequested = false;
+
+ TQEventLoop* eventLoop = TQApplication::eventLoop();
+ if (!eventLoop) return;
+
+ ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &m_cardContext);
+ if (ret != SCARD_S_SUCCESS) {
+ printf("TDECryptographicCardDevice: PCSC SCardEstablishContext cannot connect to resource manager (%lX)", ret);
+ eventLoop->exit(0);
+ return;
+ }
+
+ ret = SCardListReaders(m_cardContext, NULL, NULL, &dword_readers);
+ if (ret == SCARD_S_SUCCESS) {
+ lpstring_readers = (LPSTR)malloc(sizeof(char)*dword_readers);
+ if (lpstring_readers == NULL) {
+ printf("TDECryptographicCardDevice: insufficient memory, aborting");
+ eventLoop->exit(0);
+ return;
+ }
+
+ ret = SCardListReaders(m_cardContext, NULL, lpstring_readers, &dword_readers);
+ if (ret == SCARD_S_SUCCESS) {
+ /* Extract reader names from the null separated string */
+ char *ptr = lpstring_readers;
+ while (*ptr != '\0') {
+ readers.append(ptr);
+ ptr += strlen(ptr)+1;
+ }
+
+ free(lpstring_readers);
+
+ m_readerStates = (SCARD_READERSTATE*)calloc(readers.count(), sizeof(*m_readerStates));
+ if (m_readerStates == NULL) {
+ printf("TDECryptographicCardDevice: insufficient memory, aborting");
+ free(lpstring_readers);
+ eventLoop->exit(0);
+ return;
+ }
+
+ for (i=0; i<readers.count(); i++) {
+ m_readerStates[i].szReader = strdup(readers[i].ascii());
+ m_readerStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
+ }
+
+ ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
+ while ((ret == SCARD_S_SUCCESS) || (ret == SCARD_E_TIMEOUT)) {
+ if (m_terminationRequested) {
+ for (i=0; i<readers.count(); i++) {
+ free((char*)m_readerStates[i].szReader);
+ }
+ eventLoop->exit(0);
+ return;
+ }
+
+ for (i=0; i<readers.count(); i++) {
+ /* FIXME
+ * Find a better / more reliable way to match the card low level device to the PCSC name
+ */
+ if (!readers[i].contains(cardDevice->friendlyName())) {
+ continue;
+ }
+
+ if (first_loop) {
+ if (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT) {
+ // sleep(1); // Allow the card to settle
+ statusChanged("PRESENT", getCardATR(readers[i]));
+ }
+ first_loop = false;
+ }
+ if (m_readerStates[i].dwEventState & SCARD_STATE_CHANGED) {
+ if ((m_readerStates[i].dwCurrentState & SCARD_STATE_PRESENT)
+ && (m_readerStates[i].dwEventState & SCARD_STATE_EMPTY)) {
+ statusChanged("REMOVED", TQString::null);
+ }
+ else if ((m_readerStates[i].dwCurrentState & SCARD_STATE_EMPTY)
+ && (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT)) {
+ // sleep(1); // Allow the card to settle
+ statusChanged("INSERTED", getCardATR(readers[i]));
+ }
+ m_readerStates[i].dwCurrentState = m_readerStates[i].dwEventState;
+ }
+ else {
+ continue;
+ }
+ }
+ ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
+ }
+ }
+ }
+
+ eventLoop->exit(0);
+#endif
+}
+
+void CryptoCardDeviceWatcher::requestTermination() {
+ m_terminationRequested = true;
+}
+
+TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) {
+ unsigned int i;
+ long ret;
+ TQString atr_formatted;
+ SCARDHANDLE hCard = 0;
+ DWORD dwActiveProtocol = 0;
+ DWORD cByte = 0;
+
+ ret = SCardConnect(m_cardContext, readerName.ascii(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
+ if (ret == SCARD_S_SUCCESS) {
+ ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &cByte);
+ if (ret == SCARD_S_SUCCESS) {
+ char* data = new char[cByte];
+ ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE)data, &cByte);
+ atr_formatted = TQString::null;
+ for (i=0; i<cByte; i++) {
+ TQString formatted;
+ formatted.sprintf("%02x ", ((uint8_t)(*(data+i))));
+ atr_formatted.append(formatted.upper());
+ }
+ atr_formatted = atr_formatted.stripWhiteSpace();
+ free(data);
+ SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+ }
+ }
+ else {
+ TQString errstring = pcsc_error_code_to_string(ret);
+ if (errstring != "") {
+ atr_formatted = i18n("Unknown (%1)").arg(errstring);
+ }
+ else {
+ atr_formatted = TQString("CARD_CONNECT_FAIL (%1)").arg(ret, 0, 16);
+ }
+ }
+
+ return atr_formatted;
+}
+
+TDECryptographicCardDevice::TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn),
+ m_watcherThread(NULL),
+ m_watcherObject(NULL),
+ m_cardPresent(false) {
+ //
+}
+
+TDECryptographicCardDevice::~TDECryptographicCardDevice() {
+ enableCardMonitoring(false);
+}
+
+void TDECryptographicCardDevice::enableCardMonitoring(bool enable) {
+#ifdef WITH_PCSC
+ if (enable) {
+ if (m_watcherObject && m_watcherThread) {
+ // Monitoring thread already active; abort!
+ return;
+ }
+
+ m_watcherThread = new TQEventLoopThread();
+ m_watcherObject = new CryptoCardDeviceWatcher();
+
+ m_watcherObject->cardDevice = this;
+ m_watcherObject->moveToThread(m_watcherThread);
+ TQObject::connect(m_watcherObject, SIGNAL(statusChanged(TQString,TQString)), this, SLOT(cardStatusChanged(TQString,TQString)));
+ TQTimer::singleShot(0, m_watcherObject, SLOT(run()));
+
+ m_watcherThread->start();
+ }
+ else {
+ if (m_watcherObject) {
+ m_watcherObject->requestTermination();
+ delete m_watcherObject;
+ m_watcherObject = NULL;
+ }
+ if (m_watcherThread) {
+ m_watcherThread->wait();
+ delete m_watcherThread;
+ m_watcherThread = NULL;
+ }
+ }
+#endif
+}
+
+int TDECryptographicCardDevice::cardPresent() {
+ if (m_watcherObject && m_watcherThread) {
+ if (m_cardPresent)
+ return 1;
+ else
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+TQString TDECryptographicCardDevice::cardATR() {
+ if (m_watcherObject && m_watcherThread) {
+ if (m_cardPresent)
+ return m_cardATR;
+ else
+ return TQString::null;
+ }
+ else {
+ return TQString::null;
+ }
+}
+
+void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr) {
+ if (status == "INSERTED") {
+ m_cardPresent = true;
+ m_cardATR = atr;
+ emit(cardInserted());
+ }
+ else if (status == "REMOVED") {
+ m_cardPresent = false;
+ m_cardATR = atr;
+ emit(cardRemoved());
+ }
+ else if (status == "PRESENT") {
+ m_cardATR = atr;
+ m_cardPresent = true;
+ }
+}
+
+#include "tdecryptographiccarddevice.moc"
+#include "tdecryptographiccarddevice_private.moc"
diff --git a/tdecore/tdehw/tdecryptographiccarddevice.h b/tdecore/tdehw/tdecryptographiccarddevice.h
new file mode 100644
index 000000000..7d7a8dafc
--- /dev/null
+++ b/tdecore/tdehw/tdecryptographiccarddevice.h
@@ -0,0 +1,82 @@
+
+/* This file is part of the TDE libraries
+ Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _TDECRYPTOGRAPHICCARDDEVICE_H
+#define _TDECRYPTOGRAPHICCARDDEVICE_H
+
+#include "tdegenericdevice.h"
+
+class TQEventLoopThread;
+class CryptoCardDeviceWatcher;
+
+class TDECORE_EXPORT TDECryptographicCardDevice : public TDEGenericDevice
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ * @param Device type
+ */
+ TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn=TQString::null);
+
+ /**
+ * Destructor.
+ */
+ ~TDECryptographicCardDevice();
+
+ /**
+ * Enable / disable monitoring of insert / remove events.
+ * @param enable true to enable, false to disable.
+ */
+ void enableCardMonitoring(bool enable);
+
+ /**
+ * If monitoring of insert / remove events is enabled,
+ * return whether or not a card is present.
+ * @return -1 if status unknown, 0 if card not present,
+ * 1 if card is present.
+ */
+ int cardPresent();
+
+ /**
+ * If monitoring of insert / remove events is enabled,
+ * and a card has been inserted, return the card's ATR.
+ * @return TQString::null if no card or card status unknown.
+ */
+ TQString cardATR();
+
+ public slots:
+ void cardStatusChanged(TQString status, TQString atr);
+
+ signals:
+ void cardInserted();
+ void cardRemoved();
+
+ private:
+ TQEventLoopThread *m_watcherThread;
+ CryptoCardDeviceWatcher *m_watcherObject;
+
+ bool m_cardPresent;
+ TQString m_cardATR;
+
+ friend class TDEHardwareDevices;
+};
+
+#endif // _TDECRYPTOGRAPHICCARDDEVICE_H
diff --git a/tdecore/tdehw/tdecryptographiccarddevice_private.h b/tdecore/tdehw/tdecryptographiccarddevice_private.h
new file mode 100644
index 000000000..a82fe1ae5
--- /dev/null
+++ b/tdecore/tdehw/tdecryptographiccarddevice_private.h
@@ -0,0 +1,59 @@
+
+/* This file is part of the TDE libraries
+ Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H
+#define _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H
+
+#include "tdegenericdevice.h"
+
+#ifdef WITH_PCSC
+ #include <pcsclite.h>
+ #include <wintypes.h>
+ #include <winscard.h>
+ #include <reader.h>
+#endif
+
+class TDECryptographicCardDevice;
+
+class CryptoCardDeviceWatcher : public TQObject
+{
+ TQ_OBJECT
+
+ public:
+ CryptoCardDeviceWatcher();
+ ~CryptoCardDeviceWatcher();
+
+ public slots:
+ void run();
+ void requestTermination();
+ TQString getCardATR(TQString readerName);
+
+ signals:
+ void statusChanged(TQString, TQString);
+
+ public:
+ TDECryptographicCardDevice *cardDevice;
+
+ private:
+ bool m_terminationRequested;
+ SCARDCONTEXT m_cardContext;
+ SCARD_READERSTATE *m_readerStates;
+};
+
+#endif // _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H \ No newline at end of file
diff --git a/tdecore/tdehw/tdehardwaredevices.cpp b/tdecore/tdehw/tdehardwaredevices.cpp
index d2fd7e2f3..e3608e11c 100644
--- a/tdecore/tdehw/tdehardwaredevices.cpp
+++ b/tdecore/tdehw/tdehardwaredevices.cpp
@@ -66,6 +66,7 @@ extern "C" {
#include "tderootsystemdevice.h"
#include "tdeeventdevice.h"
#include "tdeinputdevice.h"
+#include "tdecryptographiccarddevice.h"
// Compile-time configuration
#include "config.h"
@@ -2297,7 +2298,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
}
if (usbInterfaceClass == 11) {
// Smart Card Reader
- if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::CryptographicCard);
+ if (!device) device = new TDECryptographicCardDevice(TDEGenericDeviceType::CryptographicCard);
}
if ((usbInterfaceClass == 6) && (usbInterfaceSubClass == 1) && (usbInterfaceProtocol == 1)) {
// PictBridge
diff --git a/tdecore/tdehw/tdehardwaredevices.h b/tdecore/tdehw/tdehardwaredevices.h
index 6592b8b10..2d5aeafac 100644
--- a/tdecore/tdehw/tdehardwaredevices.h
+++ b/tdecore/tdehw/tdehardwaredevices.h
@@ -53,6 +53,7 @@ extern "C" {
#include "tderootsystemdevice.h"
#include "tdeeventdevice.h"
#include "tdeinputdevice.h"
+#include "tdecryptographiccarddevice.h"
/**
* Hardware Device Access and Monitoring Library