Branch: master

c867c64a 2015-09-06 19:14:40 Timothy Pearson
Add initial LUKS key management support
M CMakeLists.txt
M tdecore/tdehw/CMakeLists.txt
M tdecore/tdehw/tdestoragedevice.cpp
M tdecore/tdehw/tdestoragedevice.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0560e7b..96b72e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,9 +60,9 @@
   WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/cmake/")
 
 
-##### user requested options ####################
+##### user requested OPTIONs ####################
 
-OPTION( WITH_ALL_OPTIONS "Enable all optional support" OFF )
+OPTION( WITH_ALL_OPTIONS "Enable all OPTIONal support" OFF )
 
 OPTION( TDE_MALLOC "Use own malloc implementation" OFF )
 OPTION( TDE_MALLOC_DEBUG "Enable debugging in fast malloc" OFF )
@@ -85,19 +85,21 @@
 OPTION( WITH_GCC_VISIBILITY "Enable fvisibility and fvisibility-inlines-hidden" ${WITH_ALL_OPTIONS} )
 OPTION( WITH_INOTIFY "Enable inotify support for tdeio" ON )
 OPTION( WITH_GAMIN "Enable FAM/GAMIN support" ${WITH_ALL_OPTIONS} )
-option( WITH_TDEHWLIB "Enable TDE hwlib globally" ON )
-option( WITH_TDEHWLIB_DAEMONS "Enable daemons for TDE hwlib" ${WITH_TDEHWLIB} )
-option( WITH_HAL "Enable HAL support" OFF )
-option( WITH_DEVKITPOWER "Enable DeviceKit Power support" OFF )
-option( WITH_LOGINDPOWER "Enable Logind/Systemd Power support" OFF )
-option( WITH_UPOWER "Enable uPower support" ${WITH_ALL_OPTIONS} )
-option( WITH_UDISKS "Enable uDisks support" ${WITH_ALL_OPTIONS} )
-option( WITH_UDISKS2 "Enable uDisks2 support" ${WITH_ALL_OPTIONS} )
-option( WITH_CONSOLEKIT "Enable ConsoleKit support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_TDEHWLIB "Enable TDE hwlib globally" ON )
+OPTION( WITH_TDEHWLIB_DAEMONS "Enable daemons for TDE hwlib" ${WITH_TDEHWLIB} )
+OPTION( WITH_HAL "Enable HAL support" OFF )
+OPTION( WITH_DEVKITPOWER "Enable DeviceKit Power support" OFF )
+OPTION( WITH_LOGINDPOWER "Enable Logind/Systemd Power support" OFF )
+OPTION( WITH_UPOWER "Enable uPower support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_UDISKS "Enable uDisks support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_UDISKS2 "Enable uDisks2 support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_CONSOLEKIT "Enable ConsoleKit support" ${WITH_ALL_OPTIONS} )
 OPTION( WITH_NETWORK_MANAGER_BACKEND "Enable network-manager support" OFF )
 OPTION( WITH_SUDO_TDESU_BACKEND "Use sudo as backend for tdesu (default is su)" OFF )
 OPTION( WITH_OLD_XDG_STD "Use the pre R14.0.0 XDG standard where both TDE and KDE are recognized in desktop files" OFF )
-option( WITH_PCSC "Enable PC/SC SmartCard support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_PCSC "Enable PC/SC SmartCard support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_PKCS "Enable PKCS support" ${WITH_ALL_OPTIONS} )
+OPTION( WITH_CRYPTSETUP "Enable cryptsetup support" ${WITH_ALL_OPTIONS} )
 OPTION( WITH_LZMA "Enable support for LZMA/XZ" ${WITH_ALL_OPTIONS} )
 OPTION( WITH_LIBBFD "Enable pretty backtraces with libbfd from GNU binutils" OFF )
 OPTION( WITH_XRANDR "Build the tderandr library" ON )
@@ -615,7 +617,7 @@
 
 find_package( BZip2 )
 if( NOT BZIP2_FOUND )
-  # FIXME I'm not sure if bzip2 are required; maybe is optional?
+  # FIXME I'm not sure if bzip2 are required; maybe is OPTIONal?
   message(FATAL_ERROR "\nbzip2 are required, but not found on your system" )
 endif( NOT BZIP2_FOUND )
 
@@ -667,6 +669,36 @@
 endif( WITH_PCSC )
 
 
+##### check for pkcs ############################
+
+if( WITH_PKCS )
+  pkg_search_module( LIBPKCS11-HELPER libpkcs11-helper-1 )
+  if( NOT LIBPKCS11-HELPER_FOUND )
+      message(FATAL_ERROR "\nPKCS support was requested, but libpkcs11-helper-1 was not found on your system" )
+  endif( NOT LIBPKCS11-HELPER_FOUND )
+  find_library( OPENSC_PKCS11_PROVIDER_LIBRARY NAMES opensc-pkcs11.so )
+  if( OPENSC_PKCS11_PROVIDER_LIBRARY )
+    set( OPENSC_PKCS11_PROVIDER_FOUND 1 )
+    message( STATUS "Found OpenSC PKCS11 provider: ${OPENSC_PKCS11_PROVIDER_LIBRARY}" )
+  endif( OPENSC_PKCS11_PROVIDER_LIBRARY )
+  if( NOT OPENSC_PKCS11_PROVIDER_FOUND )
+    tde_message_fatal( "PKCS is requested, but not OpenSC PKCS11 provider was not found on your system" )
+  endif( NOT OPENSC_PKCS11_PROVIDER_FOUND )
+  set( HAVE_PKCS 1 )
+endif( )
+
+
+##### check for pkcs ############################
+
+if( WITH_CRYPTSETUP )
+  pkg_search_module( LIBCRYPTSETUP libcryptsetup )
+  if( NOT LIBCRYPTSETUP_FOUND )
+      message(FATAL_ERROR "\ncryptsetup support was requested, but libcryptsetup was not found on your system" )
+  endif( NOT LIBCRYPTSETUP_FOUND )
+  set( HAVE_CRYPTSETUP 1 )
+endif( )
+
+
 ##### check for jpeg ############################
 
 find_package( JPEG )
diff --git a/tdecore/tdehw/CMakeLists.txt b/tdecore/tdehw/CMakeLists.txt
index 42e79ec..f1ef686 100644
--- a/tdecore/tdehw/CMakeLists.txt
+++ b/tdecore/tdehw/CMakeLists.txt
@@ -68,6 +68,12 @@
   list( APPEND TDEHW_CUSTOM_LIBRARIES ${LIBPKCS11-HELPER_LIBRARIES} )
 endif( )
 
+if( WITH_CRYPTSETUP )
+  add_definitions( -DWITH_CRYPTSETUP )
+  list( APPEND TDEHW_CUSTOM_INCLUDE_DIRS ${LIBCRYPTSETUP_INCLUDE_DIRS} )
+  list( APPEND TDEHW_CUSTOM_LIBRARIES ${LIBCRYPTSETUP_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 )
diff --git a/tdecore/tdehw/tdestoragedevice.cpp b/tdecore/tdehw/tdestoragedevice.cpp
index 6bde78f..cdf004f 100644
--- a/tdecore/tdehw/tdestoragedevice.cpp
+++ b/tdecore/tdehw/tdestoragedevice.cpp
@@ -39,6 +39,10 @@
 
 #include "config.h"
 
+#if defined(WITH_CRYPTSETUP)
+	#include <libcryptsetup.h>
+#endif
+
 // uDisks2 integration
 #if defined(WITH_UDISKS) || defined(WITH_UDISKS2)
  	#include <tqdbusdata.h>
@@ -59,20 +63,200 @@
 	TQT_DBusData convertDBUSDataToVariantData(TQT_DBusData);
 #endif // defined(WITH_UDISKS) || defined(WITH_UDISKS2)
 
-TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true) {
+#if defined(WITH_CRYPTSETUP)
+int TDEStorageDevice::cryptsetup_password_entry_callback(const char *msg, char *buf, size_t length, void *usrptr) {
+	TDEStorageDevice* sdevice = (TDEStorageDevice*)usrptr;
+
+	unsigned int passwd_len = sdevice->m_cryptDevicePassword.size();
+	if (passwd_len < length) {
+		memcpy(buf, sdevice->m_cryptDevicePassword.data(), length);
+		return passwd_len;
+	}
+	else {
+		return -1;
+	}
+}
+#endif
+
+TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true), m_cryptDevice(NULL) {
 	m_diskType = TDEDiskDeviceType::Null;
 	m_diskStatus = TDEDiskDeviceStatus::Null;
 }
 
 TDEStorageDevice::~TDEStorageDevice() {
+#if defined(WITH_CRYPTSETUP)
+	if (m_cryptDevice) {
+		crypt_free(m_cryptDevice);
+		m_cryptDevice = NULL;
+	}
+#endif
 }
 
 TDEDiskDeviceType::TDEDiskDeviceType TDEStorageDevice::diskType() {
 	return m_diskType;
 }
 
+void TDEStorageDevice::internalGetLUKSKeySlotStatus() {
+	unsigned int i;
+	crypt_keyslot_info keyslot_status;
+	TDELUKSKeySlotStatus::TDELUKSKeySlotStatus tde_keyslot_status;
+
+	m_cryptKeyslotStatus.clear();
+	for (i = 0; i < m_cryptKeySlotCount; i++) {
+		keyslot_status = crypt_keyslot_status(m_cryptDevice, i);
+		tde_keyslot_status = TDELUKSKeySlotStatus::Invalid;
+		if (keyslot_status == CRYPT_SLOT_INACTIVE) {
+			tde_keyslot_status = TDELUKSKeySlotStatus::Inactive;
+		}
+		else if (keyslot_status == CRYPT_SLOT_ACTIVE) {
+			tde_keyslot_status = TDELUKSKeySlotStatus::Active;
+		}
+		else if (keyslot_status == CRYPT_SLOT_ACTIVE_LAST) {
+			tde_keyslot_status = TDELUKSKeySlotStatus::Active | TDELUKSKeySlotStatus::Last;
+		}
+		m_cryptKeyslotStatus.append(tde_keyslot_status);
+	}
+}
+
+void TDEStorageDevice::internalInitializeLUKSIfNeeded() {
+#if defined(WITH_CRYPTSETUP)
+	int ret;
+
+	if (m_diskType & TDEDiskDeviceType::LUKS) {
+		if (!m_cryptDevice) {
+			TQString node = deviceNode();
+			if (node != "") {
+				ret = crypt_init(&m_cryptDevice, node.ascii());
+				if (ret == 0) {
+					crypt_set_password_callback(m_cryptDevice, TDEStorageDevice::cryptsetup_password_entry_callback, this);
+					ret = crypt_load(m_cryptDevice, NULL, NULL);
+					if (ret == 0) {
+						int keyslot_count;
+						m_cryptDeviceType = crypt_get_type(m_cryptDevice);
+						keyslot_count = crypt_keyslot_max(m_cryptDeviceType.ascii());
+						if (keyslot_count < 0) {
+							m_cryptKeySlotCount = 0;
+						}
+						else {
+							m_cryptKeySlotCount = keyslot_count;
+						}
+						internalGetLUKSKeySlotStatus();
+					}
+				}
+				else {
+					m_cryptDevice = NULL;
+				}
+			}
+		}
+	}
+	else {
+		if (m_cryptDevice) {
+			crypt_free(m_cryptDevice);
+			m_cryptDevice = NULL;
+		}
+	}
+#endif
+}
+
+void TDEStorageDevice::cryptSetOperationsUnlockPassword(TQByteArray password) {
+	m_cryptDevicePassword = password;
+}
+
+void TDEStorageDevice::cryptClearOperationsUnlockPassword() {
+	m_cryptDevicePassword.resize(0);
+}
+
+bool TDEStorageDevice::cryptOperationsUnlockPasswordSet() {
+	if (m_cryptDevicePassword.size() > 0) {
+		return true;
+	}
+	else {
+		return false;
+	}
+}
+
+TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptAddKey(unsigned int keyslot, TQByteArray password) {
+#if defined(WITH_CRYPTSETUP)
+	int ret;
+
+	if (m_cryptDevice) {
+		if (keyslot < m_cryptKeySlotCount) {
+			ret = crypt_keyslot_add_by_passphrase(m_cryptDevice, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), password.data(), password.size());
 ** Diff limit reached (max: 250 lines) **