diff --git a/CMakeLists.txt b/CMakeLists.txt index d2ef979d..4c8f624b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,14 +14,6 @@ set_package_properties(ZLIB PROPERTIES TYPE REQUIRED ) -find_package(LibGcrypt 1.5.0) -set_package_properties(LibGcrypt PROPERTIES - DESCRIPTION "general purpose cryptographic library based on the code from GnuPG" - URL "https://www.gnu.org/software/libgcrypt/" - PURPOSE "kwalletd needs libgcrypt to perform PBKDF2-SHA512 hashing" - TYPE REQUIRED -) - find_package(JPEG) set_package_properties(JPEG PROPERTIES DESCRIPTION "Accelerated JPEG image codec" diff --git a/kwalletd/backend/CMakeLists.txt b/kwalletd/backend/CMakeLists.txt index 746c0b85..9ff592d7 100644 --- a/kwalletd/backend/CMakeLists.txt +++ b/kwalletd/backend/CMakeLists.txt @@ -18,7 +18,7 @@ set(kwalletbackend_LIB_SRCS add_library(kwalletbackend SHARED ${kwalletbackend_LIB_SRCS}) -target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS} ${LIBGCRYPT_LIBRARIES}) +target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS}) set_target_properties(kwalletbackend PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} ) install(TARGETS kwalletbackend ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/kwalletd/backend/backendpersisthandler.cpp b/kwalletd/backend/backendpersisthandler.cpp index 38270670..104305f8 100644 --- a/kwalletd/backend/backendpersisthandler.cpp +++ b/kwalletd/backend/backendpersisthandler.cpp @@ -31,7 +31,6 @@ #include "blowfish.h" #include "cbc.h" -#include #include #define KWALLET_CIPHER_BLOWFISH_ECB 0 // this was the old KWALLET_CIPHER_BLOWFISH_CBC @@ -42,6 +41,7 @@ #define KWALLET_HASH_SHA1 0 // fallback #define KWALLET_HASH_MD5 1 // unsupported #define KWALLET_HASH_PBKDF2_SHA512 2 // used since 4.13 version +#define KWALLET_HASH_SHA512 3 // used since 4.13 version namespace KWallet { @@ -67,8 +67,7 @@ BackendPersistHandler *BackendPersistHandler::getPersistHandler(BackendCipherTyp BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[KWMAGIC_LEN]) { - if (magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC && - (magicBuf[3] == KWALLET_HASH_SHA1 || magicBuf[3] == KWALLET_HASH_PBKDF2_SHA512)) { + if (magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC && magicBuf[3] == KWALLET_HASH_SHA512) { if (blowfishHandler == 0) { blowfishHandler = new BlowfishPersistHandler(); } @@ -82,11 +81,7 @@ int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& versio assert(wb->_cipherType == BACKEND_CIPHER_BLOWFISH); version[2] = KWALLET_CIPHER_BLOWFISH_CBC; - if(!wb->_useNewHash) { - version[3] = KWALLET_HASH_SHA1; - } else { - version[3] = KWALLET_HASH_PBKDF2_SHA512; // Since 4.13 we always use PBKDF2_SHA512 - } + version[3] = KWALLET_HASH_SHA512; // Since 4.20 we always use SHA512 if (sf.write(version, 4) != 4) { sf.abort(); @@ -153,9 +148,12 @@ int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& versio wholeFile.resize(newsize); const int randBlockSize = blksz+delta; - char *randomData = (char*) gcry_random_bytes(randBlockSize, GCRY_STRONG_RANDOM); + char randomData[randBlockSize]; + ::memset(randomData, 0, randBlockSize * sizeof(char)); + for (int i = 0; i < randBlockSize; i++) { + randomData[i] = char(qrand() % (sizeof(char) * sizeof(char))); + } QByteArray randBlock(randomData, randBlockSize); - ::free(randomData); for (int i = 0; i < blksz; i++) { wholeFile[i] = randBlock[i]; diff --git a/kwalletd/backend/blowfish.cc b/kwalletd/backend/blowfish.cc index 3e7d2b42..55f92a9d 100644 --- a/kwalletd/backend/blowfish.cc +++ b/kwalletd/backend/blowfish.cc @@ -107,7 +107,7 @@ BlowFish::~BlowFish() { int BlowFish::keyLen() const { - return 448; + return 512; } @@ -117,7 +117,7 @@ bool BlowFish::readyToGo() const { bool BlowFish::setKey(void *key, int bitlength) { - if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) { + if (bitlength <= 0 || bitlength > 512 || bitlength % 8 != 0) { return false; } diff --git a/kwalletd/backend/kwalletbackend.cc b/kwalletd/backend/kwalletbackend.cc index 5d34a297..79ef396b 100644 --- a/kwalletd/backend/kwalletbackend.cc +++ b/kwalletd/backend/kwalletbackend.cc @@ -37,13 +37,10 @@ #include "blowfish.h" #include "cbc.h" -#include #include -// quick fix to get random numbers on win32 - -#define KWALLET_VERSION_MAJOR 0 -#define KWALLET_VERSION_MINOR 1 +#define KWALLET_VERSION_MAJOR 0 +#define KWALLET_VERSION_MINOR 2 using namespace KWallet; @@ -61,7 +58,6 @@ static void initKWalletDir() Backend::Backend(const QString& name, bool isPath) : d(0) , _name(name) - , _useNewHash(false) , _ref(0) , _cipherType(KWallet::BACKEND_CIPHER_UNKNOWN) { @@ -90,34 +86,6 @@ void Backend::setCipherType(BackendCipherType ct) _cipherType = ct; } -static int password2PBKDF2_SHA512(const QByteArray &password, QByteArray& hash, const QByteArray &salt) -{ - if (!gcry_check_version("1.5.0")) { - printf("libcrypt version is too old \n"); - return GPG_ERR_USER_2; - } - - gcry_error_t error; - bool static gcry_secmem_init = false; - if (!gcry_secmem_init) { - error = gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0); - if (error != 0) { - kWarning() << "Can't get secure memory:" << error; - return error; - } - gcry_secmem_init = true; - } - - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); - - error = gcry_kdf_derive(password.constData(), password.size(), - GCRY_KDF_PBKDF2, GCRY_MD_SHA512, - salt.data(), salt.size(), - PBKDF2_SHA512_ITERATIONS, PBKDF2_SHA512_KEYSIZE, hash.data()); - - return error; -} - int Backend::deref() { if (--_ref < 0) { kDebug() << "refCount negative!"; @@ -179,14 +147,11 @@ int Backend::openPreHashed(const QByteArray &passwordHash) } // check the password hash for correct size (currently fixed) - if (passwordHash.size() != 20 && passwordHash.size() != 40 && - passwordHash.size() != 56) { + if (passwordHash.size() != 20 && passwordHash.size() != 128) { return -42; // unsupported encryption scheme } _passhash = passwordHash; - _newPassHash = passwordHash; - _useNewHash = true;//Only new hash is supported return openInternal(); } @@ -227,10 +192,10 @@ int Backend::openInternal(WId w) return -4; // unknown version } - // 0 has been the MINOR version until 4.13, from that point we use it to upgrade the hash - if (magicBuf[1] == 1) { + // 0 has been the MINOR version until 4.13 + // 1 has been the MINOR version until 4.20 + if (magicBuf[1] == 2) { kDebug() << "Wallet new enough, using new hash"; - swapToNewHash(); } else if (magicBuf[1] != 0){ kDebug() << "Wallet is old, sad panda :("; return -4; // unknown version @@ -243,40 +208,6 @@ int Backend::openInternal(WId w) return phandler->read(this, db, w); } -void Backend::swapToNewHash() -{ - //Runtime error happened and we can't use the new hash - if (!_useNewHash) { - kDebug() << "Runtime error on the new hash"; - return; - } - _passhash.fill(0); // Making sure the old passhash is not around in memory - _passhash = _newPassHash; // Use the new hash, means the wallet is modern enough -} - -QByteArray Backend::createAndSaveSalt(const QString& path) const -{ - QFile saltFile(path); - saltFile.remove(); - - if (!saltFile.open(QIODevice::WriteOnly)) { - return QByteArray(); - } - - char *randomData = (char*) gcry_random_bytes(PBKDF2_SHA512_SALTSIZE, GCRY_STRONG_RANDOM); - QByteArray salt(randomData, PBKDF2_SHA512_SALTSIZE); - ::free(randomData); - - if (saltFile.write(salt) != PBKDF2_SHA512_SALTSIZE) { - kWarning() << "Could not save salt to" << path; - return QByteArray(); - } - - saltFile.close(); - - return salt; -} - int Backend::sync(WId w) { if (!_open) { return -255; // not open yet @@ -297,13 +228,7 @@ int Backend::sync(WId w) { // Write the version number QByteArray version(4, 0); version[0] = KWALLET_VERSION_MAJOR; - if (_useNewHash) { - version[1] = KWALLET_VERSION_MINOR; - // Use the sync to update the hash to PBKDF2_SHA512 - swapToNewHash(); - } else { - version[1] = 0; //was KWALLET_VERSION_MINOR before the new hash - } + version[1] = KWALLET_VERSION_MINOR; BackendPersistHandler *phandler = BackendPersistHandler::getPersistHandler(_cipherType); if (0 == phandler) { @@ -340,7 +265,6 @@ int Backend::close(bool save) { // empty the password hash _passhash.fill(0); - _newPassHash.fill(0); _open = false; @@ -542,29 +466,5 @@ bool Backend::entryDoesNotExist(const QString& folder, const QString& entry) con } void Backend::setPassword(const QByteArray &password) { - _passhash.fill(0); // empty just in case - BlowFish _bf; - CipherBlockChain bf(&_bf); - _newPassHash.resize(bf.keyLen()/8); - _newPassHash.fill(0); - - // this should be SHA-512 for release probably - _passhash = QCryptographicHash::hash(password, QCryptographicHash::Sha1); - - QByteArray salt; - QFile saltFile(KGlobal::dirs()->saveLocation("kwallet") + _name + ".salt"); - if (!saltFile.exists() || saltFile.size() == 0) { - salt = createAndSaveSalt(saltFile.fileName()); - } else { - if (!saltFile.open(QIODevice::ReadOnly)) { - salt = createAndSaveSalt(saltFile.fileName()); - } else { - salt = saltFile.readAll(); - } - } - - if (!salt.isEmpty() && password2PBKDF2_SHA512(password, _newPassHash, salt) == 0) { - kDebug() << "Setting useNewHash to true"; - _useNewHash = true; - } + _passhash = QCryptographicHash::hash(password, QCryptographicHash::Sha512); } diff --git a/kwalletd/backend/kwalletbackend.h b/kwalletd/backend/kwalletbackend.h index 004a82cf..038a7f93 100644 --- a/kwalletd/backend/kwalletbackend.h +++ b/kwalletd/backend/kwalletbackend.h @@ -28,10 +28,6 @@ #include "kwalletentry.h" #include "backendpersisthandler.h" -#define PBKDF2_SHA512_KEYSIZE 56 -#define PBKDF2_SHA512_SALTSIZE 56 -#define PBKDF2_SHA512_ITERATIONS 50000 - namespace KWallet { /** @@ -160,7 +156,6 @@ private: QString _name; QString _path; bool _open; - bool _useNewHash; QString _folder; int _ref; // Map Folder->Entries @@ -170,7 +165,6 @@ private: typedef QMap > HashMap; HashMap _hashes; QByteArray _passhash; // password hash used for saving the wallet - QByteArray _newPassHash; //Modern hash using KWALLET_HASH_PBKDF2_SHA512 BackendCipherType _cipherType; // the kind of encryption used for this wallet friend class BlowfishPersistHandler; @@ -178,8 +172,6 @@ private: // open the wallet with the password already set. This is // called internally by both open and openPreHashed. int openInternal(WId w=0); - void swapToNewHash(); - QByteArray createAndSaveSalt(const QString &path) const; }; diff --git a/kwalletd/main.cpp b/kwalletd/main.cpp index fdb6527a..49346c9e 100644 --- a/kwalletd/main.cpp +++ b/kwalletd/main.cpp @@ -35,6 +35,8 @@ #include "backend/kwalletbackend.h" //For the hash size #define BSIZE 1000 +#define KWALLET_SHA512_KEYSIZE 128 + static int pipefd = 0; static int socketfd = 0; static bool isWalletEnabled() @@ -51,10 +53,10 @@ static char *waitForHash() int totalRead = 0; int readBytes = 0; int attemps = 0; - char *buf = (char*)malloc(sizeof(char) * PBKDF2_SHA512_KEYSIZE); - memset(buf, '\0', PBKDF2_SHA512_KEYSIZE); - while(totalRead != PBKDF2_SHA512_KEYSIZE) { - readBytes = read(pipefd, buf + totalRead, PBKDF2_SHA512_KEYSIZE - totalRead); + char *buf = (char*)malloc(sizeof(char) * KWALLET_SHA512_KEYSIZE); + memset(buf, '\0', KWALLET_SHA512_KEYSIZE); + while(totalRead != KWALLET_SHA512_KEYSIZE) { + readBytes = read(pipefd, buf + totalRead, KWALLET_SHA512_KEYSIZE - totalRead); if (readBytes == -1 || attemps > 5) { free(buf); return NULL; @@ -180,7 +182,7 @@ int main(int argc, char **argv) KWalletD walletd; if (hash) { kDebug() << "LOGIN INSIDE!"; - QByteArray passHash(hash, PBKDF2_SHA512_KEYSIZE); + QByteArray passHash(hash, KWALLET_SHA512_KEYSIZE); int wallet = walletd.pamOpen(KWallet::Wallet::LocalWallet(), passHash, 0); kDebug() << "Wallet handler: " << wallet; free(hash);