summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2015-08-08 13:49:04 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2015-08-08 17:38:18 -0700
commit56bd759df1d0c750a065b8c845e93d5dfa6b549d (patch)
tree3f91093cdb475e565ae857f1c5a7fd339e2d781e /kde-apps/kwalletd
downloadgentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.gz
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.tar.bz2
gentoo-56bd759df1d0c750a065b8c845e93d5dfa6b549d.zip
proj/gentoo: Initial commit
This commit represents a new era for Gentoo: Storing the gentoo-x86 tree in Git, as converted from CVS. This commit is the start of the NEW history. Any historical data is intended to be grafted onto this point. Creation process: 1. Take final CVS checkout snapshot 2. Remove ALL ChangeLog* files 3. Transform all Manifests to thin 4. Remove empty Manifests 5. Convert all stale $Header$/$Id$ CVS keywords to non-expanded Git $Id$ 5.1. Do not touch files with -kb/-ko keyword flags. Signed-off-by: Robin H. Johnson <robbat2@gentoo.org> X-Thanks: Alec Warner <antarus@gentoo.org> - did the GSoC 2006 migration tests X-Thanks: Robin H. Johnson <robbat2@gentoo.org> - infra guy, herding this project X-Thanks: Nguyen Thai Ngoc Duy <pclouds@gentoo.org> - Former Gentoo developer, wrote Git features for the migration X-Thanks: Brian Harring <ferringb@gentoo.org> - wrote much python to improve cvs2svn X-Thanks: Rich Freeman <rich0@gentoo.org> - validation scripts X-Thanks: Patrick Lauer <patrick@gentoo.org> - Gentoo dev, running new 2014 work in migration X-Thanks: Michał Górny <mgorny@gentoo.org> - scripts, QA, nagging X-Thanks: All of other Gentoo developers - many ideas and lots of paint on the bikeshed
Diffstat (limited to 'kde-apps/kwalletd')
-rw-r--r--kde-apps/kwalletd/Manifest1
-rw-r--r--kde-apps/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch777
-rw-r--r--kde-apps/kwalletd/files/kwalletd-4.14.3-fix-random-open.patch152
-rw-r--r--kde-apps/kwalletd/kwalletd-4.14.3-r1.ebuild34
-rw-r--r--kde-apps/kwalletd/kwalletd-4.14.3-r2.ebuild37
-rw-r--r--kde-apps/kwalletd/metadata.xml8
6 files changed, 1009 insertions, 0 deletions
diff --git a/kde-apps/kwalletd/Manifest b/kde-apps/kwalletd/Manifest
new file mode 100644
index 000000000000..f52cca023dfa
--- /dev/null
+++ b/kde-apps/kwalletd/Manifest
@@ -0,0 +1 @@
+DIST kde-runtime-4.14.3.tar.xz 7867308 SHA256 78a74e519b4e897ffcee14be98eebd7b672ad2bb6e71a4aa2fe77682b5bc8605 SHA512 63b13f947915bb2eca5b85886610d1af480956b9e95a1ae77ce7c10b11576883a71bebf519335323a1f6c5dfcebe2ee0561b727cea6243756d412d9323feb244 WHIRLPOOL 4d021d826eb2ba553bb6fa320f71ed3d1f1614aef29f2d9e26285eabb9c015e6577e85ee6b0874cd1f8b89ef33cfa3dde5a6002e2178a11ede38cb8bf471a5a2
diff --git a/kde-apps/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch b/kde-apps/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch
new file mode 100644
index 000000000000..9019e17516b0
--- /dev/null
+++ b/kde-apps/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch
@@ -0,0 +1,777 @@
+From 466859302095a4ee4a9214ab24144eab7697224f Mon Sep 17 00:00:00 2001
+From: Valentin Rusu <kde@rusu.info>
+Date: Mon, 5 Jan 2015 23:00:58 +0100
+Subject: [PATCH] Backporting CBC algorithm fix from frameworks/kwallet
+
+The CBC algorithm was not enrcrypting in CBC but in ECB, despite it being
+named CBC. This problem was found by Itay Duvdevani who let us know it on the
+security mailing list. His mail eventually got forwarded to me and here is the
+fix. I also fixed the test program which was incorrectly checking the
+expected bytes.
+
+This commit corresponds to the following commits from:
+frameworks/kwallet
+ 88bc1ff01e5fdf59a13fe012aa03e31e9eb8a3b1
+ 6e588d795e6631c3c9d84d85fd3884a159b45849
+---
+ kwalletd/backend/backendpersisthandler.cpp | 67 ++++---
+ kwalletd/backend/backendpersisthandler.h | 4 +-
+ kwalletd/backend/cbc.cc | 273 ++++++++++++++++++-----------
+ kwalletd/backend/cbc.h | 44 ++---
+ kwalletd/backend/tests/testbf.cpp | 96 +++++-----
+ 5 files changed, 279 insertions(+), 205 deletions(-)
+
+diff --git a/kwalletd/backend/backendpersisthandler.cpp b/kwalletd/backend/backendpersisthandler.cpp
+index 126210a..5c321c9 100644
+--- a/kwalletd/backend/backendpersisthandler.cpp
++++ b/kwalletd/backend/backendpersisthandler.cpp
+@@ -40,14 +40,15 @@
+ #include "sha1.h"
+ #include "cbc.h"
+
+-#ifdef Q_OS_WIN
++#ifdef Q_OS_WIN
+ #include <windows.h>
+ #include <wincrypt.h>
+ #endif
+
+-#define KWALLET_CIPHER_BLOWFISH_CBC 0
++#define KWALLET_CIPHER_BLOWFISH_ECB 0 // this was the old KWALLET_CIPHER_BLOWFISH_CBC
+ #define KWALLET_CIPHER_3DES_CBC 1 // unsupported
+ #define KWALLET_CIPHER_GPG 2
++#define KWALLET_CIPHER_BLOWFISH_CBC 3
+
+ #define KWALLET_HASH_SHA1 0
+ #define KWALLET_HASH_MD5 1 // unsupported
+@@ -164,13 +165,18 @@ BackendPersistHandler *BackendPersistHandler::getPersistHandler(BackendCipherTyp
+ return 0;
+ }
+ }
+-
++
+ BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[12])
+ {
+- if (magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC &&
++ if ((magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB || magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC) &&
+ (magicBuf[3] == KWALLET_HASH_SHA1 || magicBuf[3] == KWALLET_HASH_PBKDF2_SHA512)) {
+- if (0 == blowfishHandler)
+- blowfishHandler = new BlowfishPersistHandler;
++ if (0 == blowfishHandler) {
++ bool useECBforReading = magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB;
++ if (useECBforReading) {
++ qDebug() << "this wallet uses ECB encryption. It'll be converted to CBC on next save.";
++ }
++ blowfishHandler = new BlowfishPersistHandler(useECBforReading);
++ }
+ return blowfishHandler;
+ }
+ #ifdef HAVE_QGPGME
+@@ -183,11 +189,16 @@ BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[12
+ #endif // HAVE_QGPGME
+ return 0; // unknown cipher or hash
+ }
+-
++
+ int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WId)
+ {
+ assert(wb->_cipherType == BACKEND_CIPHER_BLOWFISH);
+
++ if (_useECBforReading) {
++ qDebug() << "This wallet used ECB and is now saved using CBC";
++ _useECBforReading = false;
++ }
++
+ version[2] = KWALLET_CIPHER_BLOWFISH_CBC;
+ if(!wb->_useNewHash) {
+ version[3] = KWALLET_HASH_SHA1;
+@@ -358,7 +369,7 @@ int BlowfishPersistHandler::read(Backend* wb, QFile& db, WId)
+ assert(encrypted.size() < db.size());
+
+ BlowFish _bf;
+- CipherBlockChain bf(&_bf);
++ CipherBlockChain bf(&_bf, _useECBforReading);
+ int blksz = bf.blockSize();
+ if ((encrypted.size() % blksz) != 0) {
+ return -5; // invalid file structure
+@@ -502,7 +513,7 @@ int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WI
+ sf.abort();
+ return -5;
+ }
+-
++
+ boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+ if (0 == ctx) {
+ kDebug() << "Cannot setup OpenPGP context!";
+@@ -511,7 +522,7 @@ int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WI
+ }
+
+ assert(wb->_cipherType == BACKEND_CIPHER_GPG);
+-
++
+ QByteArray hashes;
+ QDataStream hashStream(&hashes, QIODevice::WriteOnly);
+ KMD5 md5;
+@@ -549,7 +560,7 @@ int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WI
+ dataStream << keyID;
+ dataStream << hashes;
+ dataStream << values;
+-
++
+ GpgME::Data decryptedData(dataBuffer.data(), dataBuffer.size(), false);
+ GpgME::Data encryptedData;
+ std::vector< GpgME::Key > keys;
+@@ -574,7 +585,7 @@ int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WI
+ return -4; // write error
+ }
+ }
+-
++
+ return 0;
+ }
+
+@@ -596,7 +607,7 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ while (bytes = sf.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
+ encryptedData.write(buffer, bytes);
+ }
+-
++
+ retry_label:
+ boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+ if (0 == ctx) {
+@@ -620,13 +631,13 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ }
+ return -1;
+ }
+-
++
+ decryptedData.seek(0, SEEK_SET);
+ QByteArray dataBuffer;
+ while (bytes = decryptedData.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
+ dataBuffer.append(buffer, bytes);
+ }
+-
++
+ // load the wallet from the decrypted data
+ QDataStream dataStream(dataBuffer);
+ QString keyID;
+@@ -661,10 +672,10 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ return -1;
+ }
+
+-
++
+ QDataStream hashStream(hashes);
+ QDataStream valueStream(values);
+-
++
+ quint32 hashCount;
+ hashStream >> hashCount;
+ if (hashCount > 0xFFFF) {
+@@ -675,10 +686,10 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ while (hashCount--){
+ KMD5::Digest d;
+ hashStream.readRawData(reinterpret_cast<char *>(d), 16);
+-
++
+ quint32 folderSize;
+ hashStream >> folderSize;
+-
++
+ MD5Digest ba = MD5Digest(reinterpret_cast<char *>(d));
+ QMap<MD5Digest, QList<MD5Digest> >::iterator it = wb->_hashes.insert(ba, QList<MD5Digest>());
+ while (folderSize--){
+@@ -688,27 +699,27 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ (*it).append(ba);
+ }
+ }
+-
++
+ while (folderCount--){
+ QString folder;
+ valueStream >> folder;
+-
++
+ quint32 entryCount;
+ valueStream >> entryCount;
+-
++
+ wb->_entries[folder].clear();
+-
++
+ while (entryCount--){
+ KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
+ Entry *e = new Entry;
+-
++
+ QString key;
+ valueStream >> key;
+-
++
+ qint32 x =0; // necessary to read properly
+ valueStream >> x;
+ et = static_cast<KWallet::Wallet::EntryType>(x);
+-
++
+ switch (et) {
+ case KWallet::Wallet::Password:
+ case KWallet::Wallet::Stream:
+@@ -718,7 +729,7 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ delete e;
+ continue;
+ }
+-
++
+ QByteArray a;
+ valueStream >> a;
+ e->setValue(a);
+@@ -727,7 +738,7 @@ int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+ wb->_entries[folder][key] = e;
+ }
+ }
+-
++
+ wb->_open = true;
+
+ return 0;
+diff --git a/kwalletd/backend/backendpersisthandler.h b/kwalletd/backend/backendpersisthandler.h
+index a33db48..11d67f2 100644
+--- a/kwalletd/backend/backendpersisthandler.h
++++ b/kwalletd/backend/backendpersisthandler.h
+@@ -60,11 +60,13 @@ public:
+
+ class BlowfishPersistHandler : public BackendPersistHandler {
+ public:
+- BlowfishPersistHandler() {}
++ explicit BlowfishPersistHandler(bool useECBforReading =false) : _useECBforReading(useECBforReading) {}
+ virtual ~BlowfishPersistHandler() {}
+
+ virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w);
+ virtual int read(Backend* wb, QFile& sf, WId w);
++private:
++ bool _useECBforReading;
+ };
+
+ #ifdef HAVE_QGPGME
+diff --git a/kwalletd/backend/cbc.cc b/kwalletd/backend/cbc.cc
+index 7bc5f38..772f3de 100644
+--- a/kwalletd/backend/cbc.cc
++++ b/kwalletd/backend/cbc.cc
+@@ -1,149 +1,212 @@
+ /* This file is part of the KDE project
+ Copyright (C) 2001 George Staikos <staikos@kde.org>
+-
++
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+-
++
+ 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 "cbc.h"
+ #include <string.h>
+-
+-
+-
+-CipherBlockChain::CipherBlockChain(BlockCipher *cipher) : _cipher(cipher) {
+- _next = 0L;
+- _register = 0L;
+- _len = -1;
+- _reader = _writer = 0L;
+- if (cipher) {
+- _blksz = cipher->blockSize();
+- }
++#include <kdebug.h>
++
++CipherBlockChain::CipherBlockChain(BlockCipher *cipher, bool useECBforReading) :
++ _cipher(cipher)
++ , _useECBforReading(useECBforReading)
++{
++ _next = 0L;
++ _register = 0L;
++ _len = -1;
++ _reader = _writer = 0L;
++ if (cipher) {
++ _blksz = cipher->blockSize();
++ }
+ }
+
+-
+-CipherBlockChain::~CipherBlockChain() {
+- delete[] (char *)_register;
+- _register = 0L;
+- delete[] (char *)_next;
+- _next = 0L;
++CipherBlockChain::~CipherBlockChain()
++{
++ delete[](char *)_register;
++ _register = 0L;
++ delete[](char *)_next;
++ _next = 0L;
+ }
+
+-
+-bool CipherBlockChain::setKey(void *key, int bitlength) {
+- if (_cipher) {
+- return _cipher->setKey(key, bitlength);
+- }
+- return false;
++bool CipherBlockChain::setKey(void *key, int bitlength)
++{
++ if (_cipher) {
++ return _cipher->setKey(key, bitlength);
++ }
++ return false;
+ }
+
+-
+-int CipherBlockChain::keyLen() const {
+- if (_cipher) {
+- return _cipher->keyLen();
+- }
+- return -1;
++int CipherBlockChain::keyLen() const
++{
++ if (_cipher) {
++ return _cipher->keyLen();
++ }
++ return -1;
+ }
+
+-
+-bool CipherBlockChain::variableKeyLen() const {
+- if (_cipher) {
+- return _cipher->variableKeyLen();
+- }
+- return false;
++bool CipherBlockChain::variableKeyLen() const
++{
++ if (_cipher) {
++ return _cipher->variableKeyLen();
++ }
++ return false;
+ }
+
+-
+-bool CipherBlockChain::readyToGo() const {
+- if (_cipher) {
+- return _cipher->readyToGo();
+- }
+- return false;
++bool CipherBlockChain::readyToGo() const
++{
++ if (_cipher) {
++ return _cipher->readyToGo();
++ }
++ return false;
+ }
+
+-
+-int CipherBlockChain::encrypt(void *block, int len) {
+- if (_cipher && !_reader) {
+- int rc;
+-
+- _writer |= 1;
+-
+- if (!_register) {
+- _register = new unsigned char[len];
+- _len = len;
+- memset(_register, 0, len);
+- } else if (len > _len) {
+- return -1;
+- }
+-
+- // This might be optimizable
+- char *tb = (char *)block;
+- for (int i = 0; i < len; i++) {
+- tb[i] ^= ((char *)_register)[i];
+- }
+-
+- rc = _cipher->encrypt(block, len);
+-
+- if (rc != -1) {
+- memcpy(_register, block, len);
+- }
+-
+- return rc;
+- }
+- return -1;
++void CipherBlockChain::initRegister() {
++ if (_register == 0L) {
++ size_t registerLen = _cipher->blockSize();
++ _register = new unsigned char[registerLen];
++ _len = registerLen;
++ }
++ memset(_register, 0, _len);
+ }
+
++int CipherBlockChain::encrypt(void *block, int len)
++{
++ if (_cipher && !_reader) {
++ int rc;
+
+-int CipherBlockChain::decrypt(void *block, int len) {
+- if (_cipher && !_writer) {
+- int rc;
++ _writer |= 1;
+
+- _reader |= 1;
++ initRegister();
+
+- if (!_register) {
+- _register = new unsigned char[len];
+- _len = len;
+- memset(_register, 0, len);
+- } else if (len > _len) {
+- return -1;
+- }
++ if ((len % _len) >0) {
++ kDebug() << "Block length given encrypt (" << len << ") is not a multiple of " << _len;
++ return -1;
++ }
+
+- if (!_next)
+- _next = new unsigned char[_len];
+- memcpy(_next, block, _len);
++ char *elemBlock = static_cast<char*>(block);
++ for (int b = 0; b < len/_len; b++) {
+
+- rc = _cipher->decrypt(block, len);
++ // This might be optimizable
++ char *tb = static_cast<char*>(elemBlock);
++ for (int i = 0; i < _len; i++) {
++ *tb++ ^= ((char *)_register)[i];
++ }
+
+- if (rc != -1) {
+- // This might be optimizable
+- char *tb = (char *)block;
+- for (int i = 0; i < len; i++) {
+- tb[i] ^= ((char *)_register)[i];
+- }
+- }
++ rc = _cipher->encrypt(elemBlock, _len);
+
+- void *temp;
+- temp = _next;
+- _next = _register;
+- _register = temp;
++ if (rc != -1) {
++ memcpy(_register, elemBlock, _len);
++ }
++ elemBlock += _len;
++ }
+
+- return rc;
+- }
+- return -1;
++ return rc;
++ }
++ return -1;
+ }
+
++// This is the old decrypt method, that was decrypting using ECB
++// instead of CBC
++int CipherBlockChain::decryptECB(void *block, int len) {
++ if (_cipher && !_writer) {
++ int rc;
++
++ _reader |= 1;
++
++ if (!_register) {
++ _register = new unsigned char[len];
++ _len = len;
++ memset(_register, 0, len);
++ } else if (len > _len) {
++ return -1;
++ }
++
++ if (!_next) {
++ _next = new unsigned char[_len];
++ }
++ memcpy(_next, block, _len);
++
++ rc = _cipher->decrypt(block, len);
++
++ if (rc != -1) {
++ // This might be optimizable
++ char *tb = (char *)block;
++ for (int i = 0; i < len; i++) {
++ tb[i] ^= ((char *)_register)[i];
++ }
++ }
++
++ void *temp;
++ temp = _next;
++ _next = _register;
++ _register = temp;
++
++ return rc;
++ }
++ return -1;
++}
+
+-
++int CipherBlockChain::decrypt(void *block, int len)
++{
++ if (_useECBforReading) {
++ kDebug() << "decrypting using ECB!";
++ return decryptECB(block, len);
++ }
++
++ if (_cipher && !_writer) {
++ int rc = 0;
++
++ _reader |= 1;
++
++ initRegister();
++
++ if ((len % _len) >0) {
++ kDebug() << "Block length given for decrypt (" << len << ") is not a multiple of " << _len;
++ return -1;
++ }
++
++ char *elemBlock = static_cast<char*>(block);
++ for (int b = 0; b < len/_len; b++) {
++ if (_next == 0L) {
++ _next = new unsigned char[_len];
++ }
++ memcpy(_next, elemBlock, _len);
++
++ int bytesDecrypted = _cipher->decrypt(elemBlock, _len);
++
++ if (bytesDecrypted != -1) {
++ rc += bytesDecrypted;
++ // This might be optimizable
++ char *tb = (char *)elemBlock;
++ for (int i = 0; i < _len; i++) {
++ *tb++ ^= ((char *)_register)[i];
++ }
++ }
++
++ void *temp;
++ temp = _next;
++ _next = _register;
++ _register = temp;
++
++ elemBlock += _len;
++ }
++
++ return rc;
++ }
++ return -1;
++}
+
+diff --git a/kwalletd/backend/cbc.h b/kwalletd/backend/cbc.h
+index 1ce971a..8750785 100644
+--- a/kwalletd/backend/cbc.h
++++ b/kwalletd/backend/cbc.h
+@@ -1,24 +1,22 @@
+ /* This file is part of the KDE project
+ Copyright (C) 2001 George Staikos <staikos@kde.org>
+-
++
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+-
++
+ 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 __CBC__KO__H
+ #define __CBC__KO__H
+
+@@ -33,30 +31,34 @@
+ * calls to the other will fail in this instance.
+ */
+
+-class CipherBlockChain : public BlockCipher {
+- public:
+- CipherBlockChain(BlockCipher *cipher);
+- virtual ~CipherBlockChain();
++class CipherBlockChain : public BlockCipher
++{
++public:
++ CipherBlockChain(BlockCipher *cipher, bool useECBforReading =false);
++ virtual ~CipherBlockChain();
+
+- virtual bool setKey(void *key, int bitlength);
++ virtual bool setKey(void *key, int bitlength);
+
+- virtual int keyLen() const;
++ virtual int keyLen() const;
+
+- virtual bool variableKeyLen() const;
++ virtual bool variableKeyLen() const;
+
+- virtual bool readyToGo() const;
++ virtual bool readyToGo() const;
+
+- virtual int encrypt(void *block, int len);
++ virtual int encrypt(void *block, int len);
+
+- virtual int decrypt(void *block, int len);
++ virtual int decrypt(void *block, int len);
+
+- private:
+- BlockCipher *_cipher;
+- void *_register;
+- void *_next;
+- int _len;
+- int _reader, _writer;
++private:
++ void initRegister();
++ int decryptECB(void *block, int len);
+
++ BlockCipher *_cipher;
++ void *_register;
++ void *_next;
++ int _len;
++ int _reader, _writer;
++ bool _useECBforReading;
+ };
+
+ #endif
+diff --git a/kwalletd/backend/tests/testbf.cpp b/kwalletd/backend/tests/testbf.cpp
+index 12dc746..b3d554a 100644
+--- a/kwalletd/backend/tests/testbf.cpp
++++ b/kwalletd/backend/tests/testbf.cpp
+@@ -4,64 +4,60 @@
+ #include "blowfish.h"
+ #include "cbc.h"
+
+-
+-int main() {
+-BlockCipher *bf;
+-char data[] = "This is a test.";
+-char expect[] = "\x22\x30\x7e\x2f\x42\x28\x44\x01\xda\xdf\x5a\x81\xd7\xe5\x7c\xd0";
+-char key[] = "testkey";
+-unsigned long et[] = {0x11223344};
+-
+- printf("%d: 0x11 == %d and 0x44 == %d\n", ((unsigned char *)et)[0],
+- 0x11, 0x44);
+- bf = new BlowFish();
++int main()
++{
++ BlockCipher *bf;
++ char data[] = "This is a test.";
++ char expect[] = "\x3f\x3c\x2d\xae\x8c\x7\x84\xf2\xa7\x6d\x28\xbd\xd\xb\xb8\x79";
++ char key[] = "testkey";
++ unsigned long et[] = {0x11223344};
++
++ printf("%d: 0x11 == %d and 0x44 == %d\n", ((unsigned char *)et)[0],
++ 0x11, 0x44);
++ bf = new BlowFish();
+ // bf = new CipherBlockChain(new BlowFish());
+
+- bf->setKey((void *)key, 7*8);
+-
+- if (!bf->readyToGo()) {
+- printf("Error: not ready to go!\n");
+- return -1;
+- }
++ bf->setKey((void *)key, 7 * 8);
+
+- printf("About to encrypt...\n"); fflush(stdout);
+- if (-1 == bf->encrypt((void *)data, 8)) {
+- printf("Error: encrypt failed!\n");
+- return -1;
+- }
+- printf("About to encrypt part 2...\n"); fflush(stdout);
+- bf->encrypt((void *)(data+8), 8);
+-
+- printf("Encryption done. data[] is now: ");
+- for (int i = 0; i < 16; i++) {
+- printf("0x%x ", data[i]&0xff);
+- if ((data[i]&0xff) != (expect[i]&0xff)) {
+- printf("Error. This byte failed the comparison. It should have been 0x%x.\n", expect[i]&0xff);
++ if (!bf->readyToGo()) {
++ printf("Error: not ready to go!\n");
+ return -1;
+- }
+- }
+- printf("\n");
++ }
+
+- delete bf;
+- bf = new BlowFish();
++ printf("About to encrypt...\n"); fflush(stdout);
++ if (-1 == bf->encrypt((void *)data, 16)) {
++ printf("Error: encrypt failed!\n");
++ return -1;
++ }
++
++ printf("Encryption done. data[] is now: ");
++ for (int i = 0; i < 16; i++) {
++ printf("0x%x ", data[i] & 0xff);
++ if ((data[i] & 0xff) != (expect[i] & 0xff)) {
++ printf("Error. This byte failed the comparison. It should have been 0x%x.\n", expect[i] & 0xff);
++ break;
++ }
++ }
++ printf("\n");
++
++ delete bf;
++ bf = new BlowFish();
+ // bf = new CipherBlockChain(new BlowFish());
+- bf->setKey((void *)key, 7*8);
++ bf->setKey((void *)key, 7 * 8);
+
+- printf("About to decrypt...\n"); fflush(stdout);
+- if (-1 == bf->decrypt((void *)data, 16)) {
+- printf("Error: decrypt failed!\n");
+- return -1;
+- }
+- //bf->decrypt((void *)(data+8), 8);
++ printf("About to decrypt...\n"); fflush(stdout);
++ if (-1 == bf->decrypt((void *)data, 16)) {
++ printf("Error: decrypt failed!\n");
++ return -1;
++ }
++ //bf->decrypt((void *)(data+8), 8);
+
+- printf("All done! Result... data[] = \"%s\"\n", data);
+- if (strcmp(data, "This is a test.")) {
+- printf("ERROR. Decryption failed.\n");
+- return -1;
+- }
++ printf("All done! Result... data[] = \"%s\"\n", data);
++ if (strcmp(data, "This is a test.")) {
++ printf("ERROR. Decryption failed.\n");
++ return -1;
++ }
+
+- delete bf;
++ delete bf;
+ }
+
+-
+-
+--
+2.2.1
+
diff --git a/kde-apps/kwalletd/files/kwalletd-4.14.3-fix-random-open.patch b/kde-apps/kwalletd/files/kwalletd-4.14.3-fix-random-open.patch
new file mode 100644
index 000000000000..7443e3f6cc29
--- /dev/null
+++ b/kde-apps/kwalletd/files/kwalletd-4.14.3-fix-random-open.patch
@@ -0,0 +1,152 @@
+commit 33a17ba0104cd94f2e33a3ac007b300553cdb417
+Author: Valentin Rusu <kde@rusu.info>
+Date: Mon Feb 16 22:44:07 2015 +0100
+
+ Fix for the random wallet open failure when updating
+
+ The problem seems to be caused by the use of BackendPersistHandler
+ singleton when the user has several wallets on his system and not
+ all of them have been updated to the new schema.
+
+ BUG: 343718
+
+diff --git a/kwalletd/backend/backendpersisthandler.cpp b/kwalletd/backend/backendpersisthandler.cpp
+index 5c321c9..b7f63f8 100644
+--- a/kwalletd/backend/backendpersisthandler.cpp
++++ b/kwalletd/backend/backendpersisthandler.cpp
+@@ -140,25 +140,14 @@ static int getRandomBlock(QByteArray& randBlock) {
+ #endif
+ }
+
+-
+-
+-static BlowfishPersistHandler *blowfishHandler =0;
+-#ifdef HAVE_QGPGME
+-static GpgPersistHandler *gpgHandler =0;
+-#endif // HAVE_QGPGME
+-
+ BackendPersistHandler *BackendPersistHandler::getPersistHandler(BackendCipherType cipherType)
+ {
+ switch (cipherType){
+ case BACKEND_CIPHER_BLOWFISH:
+- if (0 == blowfishHandler)
+- blowfishHandler = new BlowfishPersistHandler;
+- return blowfishHandler;
++ return new BlowfishPersistHandler;
+ #ifdef HAVE_QGPGME
+ case BACKEND_CIPHER_GPG:
+- if (0 == gpgHandler)
+- gpgHandler = new GpgPersistHandler;
+- return gpgHandler;
++ return new GpgPersistHandler;
+ #endif // HAVE_QGPGME
+ default:
+ Q_ASSERT(0);
+@@ -170,21 +159,16 @@ BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[12
+ {
+ if ((magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB || magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC) &&
+ (magicBuf[3] == KWALLET_HASH_SHA1 || magicBuf[3] == KWALLET_HASH_PBKDF2_SHA512)) {
+- if (0 == blowfishHandler) {
+- bool useECBforReading = magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB;
+- if (useECBforReading) {
+- qDebug() << "this wallet uses ECB encryption. It'll be converted to CBC on next save.";
+- }
+- blowfishHandler = new BlowfishPersistHandler(useECBforReading);
++ bool useECBforReading = magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB;
++ if (useECBforReading) {
++ qDebug() << "this wallet uses ECB encryption. It'll be converted to CBC on next save.";
+ }
+- return blowfishHandler;
++ return new BlowfishPersistHandler(useECBforReading);
+ }
+ #ifdef HAVE_QGPGME
+ if (magicBuf[2] == KWALLET_CIPHER_GPG &&
+ magicBuf[3] == 0) {
+- if (0 == gpgHandler)
+- gpgHandler = new GpgPersistHandler;
+- return gpgHandler;
++ return new GpgPersistHandler;
+ }
+ #endif // HAVE_QGPGME
+ return 0; // unknown cipher or hash
+diff --git a/kwalletd/backend/kwalletbackend.cc b/kwalletd/backend/kwalletbackend.cc
+index 7d439e3..9240103 100644
+--- a/kwalletd/backend/kwalletbackend.cc
++++ b/kwalletd/backend/kwalletbackend.cc
+@@ -266,7 +266,7 @@ int Backend::open(const QByteArray& password, WId w) {
+ if (_open) {
+ return -255; // already open
+ }
+-
++
+ setPassword(password);
+ return openInternal(w);
+ }
+@@ -287,20 +287,20 @@ int Backend::openPreHashed(const QByteArray &passwordHash)
+ if (_open) {
+ return -255; // already open
+ }
+-
++
+ // check the password hash for correct size (currently fixed)
+ if (passwordHash.size() != 20 && passwordHash.size() != 40 &&
+ passwordHash.size() != 56) {
+ return -42; // unsupported encryption scheme
+ }
+-
++
+ _passhash = passwordHash;
+ _newPassHash = passwordHash;
+ _useNewHash = true;//Only new hash is supported
+
+ return openInternal();
+ }
+-
++
+ int Backend::openInternal(WId w)
+ {
+ // No wallet existed. Let's create it.
+@@ -350,7 +350,9 @@ int Backend::openInternal(WId w)
+ if (0 == phandler){
+ return 42; // unknown cipher or hash
+ }
+- return phandler->read(this, db, w);
++ int result = phandler->read(this, db, w);
++ delete phandler;
++ return result;
+ }
+
+ void Backend::swapToNewHash()
+@@ -427,6 +429,7 @@ int Backend::sync(WId w) {
+ notification->setText( i18n("Failed to sync wallet <b>%1</b> to disk. Error codes are:\nRC <b>%2</b>\nSF <b>%3</b>. Please file a BUG report using this information to bugs.kde.org").arg(_name).arg(rc).arg(sf.errorString()) );
+ notification->sendEvent();
+ }
++ delete phandler;
+ return rc;
+ }
+
+@@ -439,7 +442,7 @@ int Backend::close(bool save) {
+ return rc;
+ }
+ }
+-
++
+ // do the actual close
+ for (FolderMap::ConstIterator i = _entries.constBegin(); i != _entries.constEnd(); ++i) {
+ for (EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
+@@ -447,13 +450,13 @@ int Backend::close(bool save) {
+ }
+ }
+ _entries.clear();
+-
++
+ // empty the password hash
+ _passhash.fill(0);
+ _newPassHash.fill(0);
+
+ _open = false;
+-
++
+ return 0;
+ }
+
diff --git a/kde-apps/kwalletd/kwalletd-4.14.3-r1.ebuild b/kde-apps/kwalletd/kwalletd-4.14.3-r1.ebuild
new file mode 100644
index 000000000000..48e52a364ab2
--- /dev/null
+++ b/kde-apps/kwalletd/kwalletd-4.14.3-r1.ebuild
@@ -0,0 +1,34 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+
+KMNAME="kde-runtime"
+inherit kde4-meta
+
+DESCRIPTION="KDE Password Server"
+KEYWORDS="amd64 ~arm ppc ppc64 x86 ~x86-fbsd ~amd64-linux ~x86-linux"
+IUSE="debug gpg"
+
+DEPEND="
+ gpg? (
+ app-crypt/gpgme
+ $(add_kdebase_dep kdepimlibs)
+ )
+"
+RDEPEND="${DEPEND}"
+
+RESTRICT="test"
+# testpamopen crashes with a buffer overflow (__fortify_fail)
+
+PATCHES=( "${FILESDIR}/${P}-CVE-2013-7252.patch" )
+
+src_configure() {
+ local mycmakeargs=(
+ $(cmake-utils_use_find_package gpg Gpgme)
+ $(cmake-utils_use_find_package gpg QGpgme)
+ )
+
+ kde4-base_src_configure
+}
diff --git a/kde-apps/kwalletd/kwalletd-4.14.3-r2.ebuild b/kde-apps/kwalletd/kwalletd-4.14.3-r2.ebuild
new file mode 100644
index 000000000000..72afa54fa6c0
--- /dev/null
+++ b/kde-apps/kwalletd/kwalletd-4.14.3-r2.ebuild
@@ -0,0 +1,37 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+
+KMNAME="kde-runtime"
+inherit kde4-meta
+
+DESCRIPTION="KDE Password Server"
+KEYWORDS="amd64 ~arm ppc ~ppc64 ~x86 ~x86-fbsd ~amd64-linux ~x86-linux"
+IUSE="debug gpg"
+
+DEPEND="
+ gpg? (
+ app-crypt/gpgme
+ $(add_kdebase_dep kdepimlibs)
+ )
+"
+RDEPEND="${DEPEND}"
+
+RESTRICT="test"
+# testpamopen crashes with a buffer overflow (__fortify_fail)
+
+PATCHES=(
+ "${FILESDIR}/${P}-CVE-2013-7252.patch"
+ "${FILESDIR}/${P}-fix-random-open.patch"
+)
+
+src_configure() {
+ local mycmakeargs=(
+ $(cmake-utils_use_find_package gpg Gpgme)
+ $(cmake-utils_use_find_package gpg QGpgme)
+ )
+
+ kde4-base_src_configure
+}
diff --git a/kde-apps/kwalletd/metadata.xml b/kde-apps/kwalletd/metadata.xml
new file mode 100644
index 000000000000..ed9327ee435a
--- /dev/null
+++ b/kde-apps/kwalletd/metadata.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <herd>kde</herd>
+ <use>
+ <flag name="gpg">Support wallets with GnuPG encryption additionally to default blowfish-encrypted file</flag>
+ </use>
+</pkgmetadata>