diff options
author | Timothy Pearson <[email protected]> | 2015-09-14 15:08:14 -0500 |
---|---|---|
committer | Timothy Pearson <[email protected]> | 2015-09-14 15:08:14 -0500 |
commit | 402781f094e9a2450942f9d58215da281ba080c2 (patch) | |
tree | 2132931e47d6028e9aed2b9c302740dae0a2c29d /tdecore/tdehw/tdecryptographiccarddevice.cpp | |
parent | ffa54887cef6a8e36b2d63e7e9139ac11863a525 (diff) | |
download | tdelibs-402781f094e9a2450942f9d58215da281ba080c2.tar.gz tdelibs-402781f094e9a2450942f9d58215da281ba080c2.zip |
Add cryptographic card decryption method to tdehwlib
Diffstat (limited to 'tdecore/tdehw/tdecryptographiccarddevice.cpp')
-rw-r--r-- | tdecore/tdehw/tdecryptographiccarddevice.cpp | 227 |
1 files changed, 212 insertions, 15 deletions
diff --git a/tdecore/tdehw/tdecryptographiccarddevice.cpp b/tdecore/tdehw/tdecryptographiccarddevice.cpp index 1fb1849ca..99c00b9e5 100644 --- a/tdecore/tdehw/tdecryptographiccarddevice.cpp +++ b/tdecore/tdehw/tdecryptographiccarddevice.cpp @@ -61,6 +61,8 @@ CryptoCardDeviceWatcher::CryptoCardDeviceWatcher() { #ifdef WITH_PCSC m_readerStates = NULL; #endif + m_cardPINPromptDone = true; + m_pinCallbacksEnabled = false; } CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() { @@ -189,6 +191,11 @@ void CryptoCardDeviceWatcher::requestTermination() { m_terminationRequested = true; } +void CryptoCardDeviceWatcher::setProvidedPin(TQString pin) { + m_cardPIN = pin; + m_cardPINPromptDone = true; +} + TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) { #ifdef WITH_PCSC unsigned int i; @@ -231,21 +238,54 @@ TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) { #endif } +void CryptoCardDeviceWatcher::enablePINEntryCallbacks(bool enable) { + m_pinCallbacksEnabled = enable; +} + +TQString CryptoCardDeviceWatcher::doPinRequest(TQString prompt) { + if (!m_pinCallbacksEnabled) { + return TQString::null; + } + + m_cardPINPromptDone = false; + emit(pinRequested(prompt)); + while (!m_cardPINPromptDone) { + usleep(100); + } + + if (m_cardPIN.length() > 0) { + return m_cardPIN; + } + else { + return TQString::null; + } +} + #ifdef WITH_PKCS static void pkcs_log_hook(IN void * const global_data, IN unsigned flags, IN const char * const format, IN va_list args) { vprintf(format, args); printf("\n"); } + +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) { + CryptoCardDeviceWatcher* watcher = (CryptoCardDeviceWatcher*)global_data; + TQString providedPin = watcher->doPinRequest(i18n("Please enter the PIN for '%1'").arg(token->display)); + if (providedPin.length() > 0) { + snprintf(pin, pin_max, "%s", providedPin.ascii()); + + // Success + return 1; + } + else { + // Abort + return 0; + } +} #endif -int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { +int CryptoCardDeviceWatcher::initializePkcs() { #if WITH_PKCS - int ret = -1; - CK_RV rv; - pkcs11h_certificate_id_list_t issuers; - pkcs11h_certificate_id_list_t certs; - printf("Initializing pkcs11-helper\n"); if ((rv = pkcs11h_initialize()) != CKR_OK) { printf("pkcs11h_initialize failed: %s\n", pkcs11h_getMessage(rv)); @@ -253,29 +293,51 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { } printf("Registering pkcs11-helper hooks\n"); - if ((rv = pkcs11h_setLogHook(pkcs_log_hook, NULL)) != CKR_OK) { + if ((rv = pkcs11h_setLogHook(pkcs_log_hook, this)) != CKR_OK) { printf("pkcs11h_setLogHook failed: %s\n", pkcs11h_getMessage(rv)); return -1; } pkcs11h_setLogLevel(PKCS11H_LOG_WARN); + // pkcs11h_setLogLevel(PKCS11H_LOG_DEBUG2); #if 0 if ((rv = pkcs11h_setTokenPromptHook(_pkcs11h_hooks_token_prompt, NULL)) != CKR_OK) { printf("pkcs11h_setTokenPromptHook failed: %s\n", pkcs11h_getMessage(rv)); return -1; } - if ((rv = pkcs11h_setPINPromptHook(_pkcs11h_hooks_pin_prompt, NULL)) != CKR_OK) { +#endif + + if ((rv = pkcs11h_setPINPromptHook(pkcs_pin_hook, this)) != CKR_OK) { printf("pkcs11h_setPINPromptHook failed: %s\n", pkcs11h_getMessage(rv)); return -1; } -#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) { printf("pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv)); return -1; } - rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_NONE, &issuers, &certs); + return 0; +#else + return -1; +#endif +} + +int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { +#if WITH_PKCS + int ret = -1; + + CK_RV rv; + pkcs11h_certificate_id_list_t issuers; + pkcs11h_certificate_id_list_t certs; + + if (initializePkcs() < 0) { + printf("Unable to initialize PKCS\n"); + return -1; + } + + rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, &issuers, &certs); if ((rv != CKR_OK) || (certs == NULL)) { printf("Cannot enumerate certificates: %s\n", pkcs11h_getMessage(rv)); return -1; @@ -288,13 +350,14 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { printf("Certificate %d name: '%s'\n", i, label.ascii()); pkcs11h_certificate_t certificate; - rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_NONE, PKCS11H_PIN_CACHE_INFINITE, &certificate); + rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &certificate); if (rv != CKR_OK) { - printf("Can not read certificate: %s\n", pkcs11h_getMessage(rv)); + printf("Cannot read certificate: %s\n", pkcs11h_getMessage(rv)); pkcs11h_certificate_freeCertificateId(certs->certificate_id); ret = -1; break; } + pkcs11h_certificate_freeCertificateId(certs->certificate_id); pkcs11h_openssl_session_t openssl_session = NULL; @@ -335,13 +398,12 @@ int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) { printf("Unable to copy X509 certificate\n"); } - pkcs11h_certificate_freeCertificateIdList(issuers); - pkcs11h_openssl_freeSession(openssl_session); - i++; } + pkcs11h_certificate_freeCertificateIdList(issuers); + return ret; #else return -1; @@ -386,6 +448,7 @@ void TDECryptographicCardDevice::enableCardMonitoring(bool enable) { m_watcherObject->cardDevice = this; m_watcherObject->moveToThread(m_watcherThread); TQObject::connect(m_watcherObject, SIGNAL(statusChanged(TQString,TQString)), this, SLOT(cardStatusChanged(TQString,TQString))); + TQObject::connect(m_watcherObject, SIGNAL(pinRequested(TQString)), this, SLOT(workerRequestedPin(TQString))); TQTimer::singleShot(0, m_watcherObject, SLOT(run())); m_watcherThread->start(); @@ -407,6 +470,12 @@ void TDECryptographicCardDevice::enableCardMonitoring(bool enable) { #endif } +void TDECryptographicCardDevice::enablePINEntryCallbacks(bool enable) { + if (m_watcherObject) { + m_watcherObject->enablePINEntryCallbacks(enable); + } +} + int TDECryptographicCardDevice::cardPresent() { if (m_watcherObject && m_watcherThread) { if (m_cardPresent) @@ -462,6 +531,134 @@ void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr } } +void TDECryptographicCardDevice::setProvidedPin(TQString pin) { + if (m_watcherObject) { + m_watcherObject->setProvidedPin(pin); + } +} + +void TDECryptographicCardDevice::workerRequestedPin(TQString prompt) { + emit(pinRequested(prompt, this)); +} + +int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQByteArray &ciphertext, TQByteArray &plaintext, TQString *errstr) { +#if WITH_PKCS + int ret = -1; + + if (!m_watcherObject) { + if (errstr) *errstr = i18n("Card watcher object not available"); + return -1; + } + + CK_RV rv; + pkcs11h_certificate_id_list_t issuers; + pkcs11h_certificate_id_list_t certs; + + if (m_watcherObject->initializePkcs() < 0) { + if (errstr) *errstr = i18n("Unable to initialize PKCS"); + return -1; + } + + rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, &issuers, &certs); + if ((rv != CKR_OK) || (certs == NULL)) { + if (errstr) *errstr = i18n("Cannot enumerate certificates: %1").arg(pkcs11h_getMessage(rv)); + return -1; + } + + int i = 0; + for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) { + TQString label = cert->certificate_id->displayName; + + pkcs11h_certificate_t certificate; + rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL, PKCS11H_PIN_CACHE_INFINITE, &certificate); + if (rv != CKR_OK) { + if (errstr) *errstr = i18n("Cannot read certificate: %1").arg(pkcs11h_getMessage(rv)); + pkcs11h_certificate_freeCertificateId(certs->certificate_id); + ret = -1; + break; + } + + pkcs11h_certificate_freeCertificateId(certs->certificate_id); + + pkcs11h_openssl_session_t openssl_session = NULL; + if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) { + if (errstr) *errstr = i18n("Cannot initialize openssl session to retrieve cryptographic objects"); + pkcs11h_certificate_freeCertificate(certificate); + ret = -1; + break; + } + + if (ciphertext.size() < 16) { + if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too small")); + ret = -2; + continue; + } + + // Get certificate data + X509* x509_local; + x509_local = pkcs11h_openssl_session_getX509(openssl_session); + if (!x509_local) { + if (errstr) *errstr = i18n("Cannot get X509 object\n"); + ret = -1; + } + + // Extract public key from X509 certificate + EVP_PKEY* x509_pubkey = NULL; + RSA* rsa_pubkey = NULL; + x509_pubkey = X509_get_pubkey(x509_local); + if (x509_pubkey) { + rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey); + } + + // Try to get RSA parameters + if (rsa_pubkey) { + unsigned int rsa_length = RSA_size(rsa_pubkey); + if (ciphertext.size() > rsa_length) { + if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too large")); + ret = -2; + continue; + } + } + + size_t size = 0; + // Determine output buffer size + rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), NULL, &size); + if (rv != CKR_OK) { + if (errstr) *errstr = i18n("Cannot determine decrypted message length: %1").arg(pkcs11h_getMessage(rv)); + ret = -2; + } + else { + // Decrypt data + plaintext.resize(size); + rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), (unsigned char*)plaintext.data(), &size); + if (rv != CKR_OK) { + if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(pkcs11h_getMessage(rv)); + ret = -2; + } + else { + if (errstr) *errstr = TQString::null; + ret = 0; + } + } + + pkcs11h_openssl_freeSession(openssl_session); + + // Only interested in first certificate for now + // FIXME + // If cards with multiple certificates are used this should be modified to try decryption + // using each certificate in turn... + break; + + i++; + } + pkcs11h_certificate_freeCertificateIdList(issuers); + + return ret; +#else + return -1; +#endif +} + int TDECryptographicCardDevice::createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate) { unsigned int i; int retcode = -1; |