From ffa54887cef6a8e36b2d63e7e9139ac11863a525 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 14 Sep 2015 03:54:16 -0500 Subject: [PATCH] Add additional cryptographic card functions to tdehwlib Fix FTBFS on old distributions --- CMakeLists.txt | 9 +++ config.h.cmake | 3 + tdecore/tdehw/tdecryptographiccarddevice.cpp | 76 ++++++++++++++++---- tdecore/tdehw/tdecryptographiccarddevice.h | 10 +++ tdecore/tdehw/tdestoragedevice.cpp | 28 +++++--- 5 files changed, 103 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96b72e0b6..4621f92f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -696,6 +696,15 @@ if( WITH_CRYPTSETUP ) message(FATAL_ERROR "\ncryptsetup support was requested, but libcryptsetup was not found on your system" ) endif( NOT LIBCRYPTSETUP_FOUND ) set( HAVE_CRYPTSETUP 1 ) + if ( HAVE_CRYPTSETUP ) + check_c_source_compiles(" + #include + int main(int argc, char *argv[]) { crypt_keyslot_info status = CRYPT_SLOT_INVALID; return 0; } " + HAVE_NEW_CRYPTSETUP ) + endif( ) + if ( NOT HAVE_NEW_CRYPTSETUP ) + set( CRYPTSETUP_OLD_API 1 ) + endif( ) endif( ) diff --git a/config.h.cmake b/config.h.cmake index 0e0e4a60d..0eb6f6781 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -148,6 +148,9 @@ /* Defines if your system has the crypt function */ #cmakedefine HAVE_CRYPT 1 +/* Defines if your system uses the old cryptsetup API */ +#cmakedefine CRYPTSETUP_OLD_API 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_CTYPE_H 1 diff --git a/tdecore/tdehw/tdecryptographiccarddevice.cpp b/tdecore/tdehw/tdecryptographiccarddevice.cpp index 43805ef55..1fb1849ca 100644 --- a/tdecore/tdehw/tdecryptographiccarddevice.cpp +++ b/tdecore/tdehw/tdecryptographiccarddevice.cpp @@ -31,6 +31,7 @@ #include "tdeglobal.h" #include "tdelocale.h" +#include "tdeapplication.h" #include "tdehardwaredevices.h" @@ -130,6 +131,7 @@ void CryptoCardDeviceWatcher::run() { if (m_terminationRequested) { for (i=0; iexit(0); return; @@ -209,7 +211,7 @@ TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) { atr_formatted.append(formatted.upper()); } atr_formatted = atr_formatted.stripWhiteSpace(); - free(data); + delete [] data; SCardDisconnect(hCard, SCARD_LEAVE_CARD); } } @@ -243,7 +245,6 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { CK_RV rv; pkcs11h_certificate_id_list_t issuers; pkcs11h_certificate_id_list_t certs; - pkcs11h_certificate_id_t find = NULL; printf("Initializing pkcs11-helper\n"); if ((rv = pkcs11h_initialize()) != CKR_OK) { @@ -269,7 +270,7 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { } #endif printf("Adding provider '%s'\n", OPENSC_PKCS11_PROVIDER_LIBRARY); - 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) { + 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) { printf("pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv)); return -1; } @@ -284,17 +285,17 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { int i = 0; for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) { TQString label = cert->certificate_id->displayName; - printf("The name of the %d certficate is %s\n", i, label.ascii()); + printf("Certificate %d name: '%s'\n", i, label.ascii()); pkcs11h_certificate_t certificate; - rv = pkcs11h_certificate_create(find, NULL, PKCS11H_PROMPT_MASK_ALLOW_NONE, PKCS11H_PIN_CACHE_INFINITE, &certificate); + rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_NONE, PKCS11H_PIN_CACHE_INFINITE, &certificate); if (rv != CKR_OK) { printf("Can not read certificate: %s\n", pkcs11h_getMessage(rv)); - pkcs11h_certificate_freeCertificateId(find); + pkcs11h_certificate_freeCertificateId(certs->certificate_id); ret = -1; break; } - pkcs11h_certificate_freeCertificateId(find); + pkcs11h_certificate_freeCertificateId(certs->certificate_id); pkcs11h_openssl_session_t openssl_session = NULL; if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) { @@ -335,7 +336,6 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { } pkcs11h_certificate_freeCertificateIdList(issuers); - pkcs11h_certificate_freeCertificateIdList(certs); pkcs11h_openssl_freeSession(openssl_session); @@ -393,14 +393,16 @@ void TDECryptographicCardDevice::enableCardMonitoring(bool enable) { 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; } + if (m_watcherObject) { + delete m_watcherObject; + m_watcherObject = NULL; + } } #endif } @@ -431,10 +433,12 @@ TQString TDECryptographicCardDevice::cardATR() { X509CertificatePtrList TDECryptographicCardDevice::cardX509Certificates() { if (m_watcherObject && m_watcherThread) { - if (m_cardPresent) + if (m_cardPresent) { return m_cardCertificates; - else + } + else { return X509CertificatePtrList(); + } } else { return X509CertificatePtrList(); @@ -458,5 +462,53 @@ void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr } } +int TDECryptographicCardDevice::createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate) { + unsigned int i; + int retcode = -1; + + // Extract public key from X509 certificate + EVP_PKEY* x509_pubkey = NULL; + RSA* rsa_pubkey = NULL; + x509_pubkey = X509_get_pubkey(certificate); + if (x509_pubkey) { + rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey); + } + + if (rsa_pubkey) { + // Determine encryption parameters + // NOTE + // RSA_PKCS1_OAEP_PADDING is preferred but cannot be decoded from + // the command line via openssl at this time of this writing. + int rsa_padding_style = RSA_PKCS1_PADDING; + unsigned int rsa_length = RSA_size(rsa_pubkey); + unsigned int max_key_length = rsa_length - 41; + + // Create a new random key as the plaintext + plaintext.resize(max_key_length); + for (i=0; i < max_key_length; i++) { + plaintext[i] = TDEApplication::random(); + } + + // Encrypt data + ciphertext.resize(rsa_length); + if (RSA_public_encrypt(plaintext.size(), (unsigned char *)plaintext.data(), (unsigned char *)ciphertext.data(), rsa_pubkey, rsa_padding_style) < 0) { + retcode = -2; + } + + // Success! + retcode = 0; + } + + // Clean up + if (rsa_pubkey) { + RSA_free(rsa_pubkey); + } + if (x509_pubkey) { + EVP_PKEY_free(x509_pubkey); + } + + return retcode; +} + #include "tdecryptographiccarddevice.moc" #include "tdecryptographiccarddevice_private.moc" diff --git a/tdecore/tdehw/tdecryptographiccarddevice.h b/tdecore/tdehw/tdecryptographiccarddevice.h index fd0364fd8..c9de6091b 100644 --- a/tdecore/tdehw/tdecryptographiccarddevice.h +++ b/tdecore/tdehw/tdecryptographiccarddevice.h @@ -82,6 +82,16 @@ class TDECORE_EXPORT TDECryptographicCardDevice : public TDEGenericDevice */ X509CertificatePtrList cardX509Certificates(); + /** + * Create a new random key and encrypt with the public key + * contained in the given certificate. + * @param plaintext Generated (decrypted) random key + * @param ciphertext Encrypted key + * @param certificate X509 certificate containing the public key to use + * @return 0 on success, -1 on general failure, -2 on encryption failure + */ + static int createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate); + public slots: void cardStatusChanged(TQString status, TQString atr); diff --git a/tdecore/tdehw/tdestoragedevice.cpp b/tdecore/tdehw/tdestoragedevice.cpp index 781c08885..1b4be9283 100644 --- a/tdecore/tdehw/tdestoragedevice.cpp +++ b/tdecore/tdehw/tdestoragedevice.cpp @@ -41,9 +41,17 @@ #include "config.h" #if defined(WITH_CRYPTSETUP) - #include - #ifndef CRYPT_SLOT_INACTIVE - #define CRYPTSETUP_OLD_API + #ifdef CRYPTSETUP_OLD_API + #define class cryptsetup_class + #define CRYPT_SLOT_INVALID INVALID + #define CRYPT_SLOT_INACTIVE INACTIVE + #define CRYPT_SLOT_ACTIVE ACTIVE + #define CRYPT_SLOT_BUSY BUSY + #define CRYPT_SLOT_ACTIVE_LAST ACTIVE + #include + #undef class + #else + #include #endif #endif @@ -102,9 +110,6 @@ TDEDiskDeviceType::TDEDiskDeviceType TDEStorageDevice::diskType() { void TDEStorageDevice::internalGetLUKSKeySlotStatus() { #if defined(WITH_CRYPTSETUP) -#ifdef CRYPTSETUP_OLD_API - kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl; -#else unsigned int i; crypt_keyslot_info keyslot_status; TDELUKSKeySlotStatus::TDELUKSKeySlotStatus tde_keyslot_status; @@ -125,14 +130,10 @@ void TDEStorageDevice::internalGetLUKSKeySlotStatus() { m_cryptKeyslotStatus.append(tde_keyslot_status); } #endif -#endif } void TDEStorageDevice::internalInitializeLUKSIfNeeded() { #if defined(WITH_CRYPTSETUP) -#ifdef CRYPTSETUP_OLD_API - kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl; -#else int ret; if (m_diskType & TDEDiskDeviceType::LUKS) { @@ -145,8 +146,14 @@ void TDEStorageDevice::internalInitializeLUKSIfNeeded() { ret = crypt_load(m_cryptDevice, NULL, NULL); if (ret == 0) { int keyslot_count; +#ifdef CRYPTSETUP_OLD_API + kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl; + m_cryptDeviceType = TQString::null; + keyslot_count = 0; +#else m_cryptDeviceType = crypt_get_type(m_cryptDevice); keyslot_count = crypt_keyslot_max(m_cryptDeviceType.ascii()); +#endif if (keyslot_count < 0) { m_cryptKeySlotCount = 0; } @@ -169,7 +176,6 @@ void TDEStorageDevice::internalInitializeLUKSIfNeeded() { } } #endif -#endif } void TDEStorageDevice::cryptSetOperationsUnlockPassword(TQByteArray password) {