Revision bumps backports upstream patch to fix CVE-2013-7252, bug #496768.
authorJohannes Huber <johu@gentoo.org>
Tue, 20 Jan 2015 21:07:59 +0000 (21:07 +0000)
committerJohannes Huber <johu@gentoo.org>
Tue, 20 Jan 2015 21:07:59 +0000 (21:07 +0000)
Package-Manager: portage-2.2.15/cvs/Linux x86_64
Manifest-Sign-Key: 0xF3CFD2BD

kde-base/kwalletd/ChangeLog
kde-base/kwalletd/Manifest
kde-base/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch [new file with mode: 0644]
kde-base/kwalletd/kwalletd-4.14.3-r1.ebuild [new file with mode: 0644]

index d8a6ff2558fcb52c4166751399e0beabc2e6c8ed..2d3f013d7786a44bf40ff81509109d99c8170e75 100644 (file)
@@ -1,6 +1,12 @@
 # ChangeLog for kde-base/kwalletd
-# Copyright 1999-2014 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/kde-base/kwalletd/ChangeLog,v 1.228 2014/12/11 15:45:07 mrueg Exp $
+# Copyright 1999-2015 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-x86/kde-base/kwalletd/ChangeLog,v 1.229 2015/01/20 21:07:52 johu Exp $
+
+*kwalletd-4.14.3-r1 (20 Jan 2015)
+
+  20 Jan 2015; Johannes Huber <johu@gentoo.org>
+  +files/kwalletd-4.14.3-CVE-2013-7252.patch, +kwalletd-4.14.3-r1.ebuild:
+  Revision bumps backports upstream patch to fix CVE-2013-7252, bug #496768.
 
   11 Dec 2014; Manuel RĂ¼ger <mrueg@gentoo.org> -kwalletd-4.14.2.ebuild:
   Remove KDE SC 4.14.2
index 298ac78e1af384147efb35248511074dc152d01d..068e4a4981408507c942a4d92eb80364ebc4e465 100644 (file)
@@ -1,6 +1,28 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+AUX kwalletd-4.14.3-CVE-2013-7252.patch 21806 SHA256 08d048f6a90be17d51522660d02acda1fdb55fc375ce0214bc554ef2c3d940c4 SHA512 f1091235ab0ad4f6ef8e52ef2d2b5090c195596ba7ff21221c7b69935db5ad37741340c7cd24d7da0e931e05504b3d2b5800c1c7a368a4f9c1589462cb7b5892 WHIRLPOOL 2d091daa76f699b02a1e58150b0d542dcbcca57eb4c1dd85dc1760247c55ec0d68fecb758a9bc619e3720bfca152d8ed7ca1380b9a84455dd40c3e4fddf322a8
 DIST kde-runtime-4.12.5.tar.xz 7856352 SHA256 b43e1aebd7e9dd13677f2205bb6eef7ee02a7085ae9fd34a39bad55d5df56fe7 SHA512 777916ea15cf5e36218e36a2b67758dbaa2bbdbdc50c3c67d65b69085416502962ece4977a81a182197ab733f44735ddf9b539a3c76cc70a98bdcece368491dd WHIRLPOOL 8c7adec7a55d8126ac7aba4964c42057831c7d26f69e33aa319adc701ef7f368d094c9b3e88b12e729682aa0da8789b5b69cab55737b4be1d1a9020649dc5ac5
 DIST kde-runtime-4.14.3.tar.xz 7867308 SHA256 78a74e519b4e897ffcee14be98eebd7b672ad2bb6e71a4aa2fe77682b5bc8605 SHA512 63b13f947915bb2eca5b85886610d1af480956b9e95a1ae77ce7c10b11576883a71bebf519335323a1f6c5dfcebe2ee0561b727cea6243756d412d9323feb244 WHIRLPOOL 4d021d826eb2ba553bb6fa320f71ed3d1f1614aef29f2d9e26285eabb9c015e6577e85ee6b0874cd1f8b89ef33cfa3dde5a6002e2178a11ede38cb8bf471a5a2
 EBUILD kwalletd-4.12.5.ebuild 694 SHA256 d938bb7c226149dd7150f0f577fdaa5fa9a0bd70313aad0037c106bf3213fe4e SHA512 75c43d6bfe4164181bbe60d4e5c94a352b4731c07daa19e9005f727da35cfab45f2f2155aa7ee2e6790cd18de473c8d60d1526006b4ac7e4d2331a67dc07e6e3 WHIRLPOOL 6fa8f0c0f0600c8981bd8f517a9d27e832561d2c80420aac8a304956d93ba8a01cfe1a188b54832fb42e3127a2f0eb29ab3c4932c05d89283f8f38432a497ef5
+EBUILD kwalletd-4.14.3-r1.ebuild 781 SHA256 9f287cb559c5a96781cc556a9f95497aff3af55ff2d5934d7152e53fe5be8964 SHA512 4ec2e6ba792d59b7f4fc1497e66d1ec9d3490ff7fb5a0873345ee8733dcd8e3895a488411de2cb1873ad73b01e85cea01ab2fe09f85dd14ab1e6a8217718fce2 WHIRLPOOL ef3d5b07dcdaf684f80e0eee49bbe66d6a597a1028676bb87a8549581f4c4165f4ea49cebb77aae5fde5af789e877da764cd68b65310f25f06e678e95f08e8b2
 EBUILD kwalletd-4.14.3.ebuild 728 SHA256 e17ced270175345cf919a706cb40d0ef334d6901bb6a98939a4639d972d32ed5 SHA512 a4582692d9766c09373625b14c20e61937999f1dd48699fb6c9651ac555b3420d7f93b93de4f4caf144da85d93e60cfce5ac36d3cb87bef0e84adfa8d645f109 WHIRLPOOL c2ce234062e1941fac0414900f7fe6bb0734c09aada8afe93bc8ab4904135153688a6d4254e9b314af0d1a0f1af9cdbfad2dc4cb496640b207c34b725a5a7c5d
-MISC ChangeLog 26788 SHA256 48d523f2c7228fde92c426291bf72ff6838e5ca64d3ae9341f3aa153bacd4a49 SHA512 4c6aae330188795e406c4a0bf1a8b88e8d23942112b68987dc861a3327103661b472e1e93ceba058429eb748f42e0a92c528e36a264440f06263ff6fdca30fd7 WHIRLPOOL b696eb481ebbb052146354714204b080d526a53ec2e383a137ae376f40db1189da64f1d713a1e75b25458fc1dc09ef97f75cb996516226a3a5c03fac4c9d3fbc
+MISC ChangeLog 27022 SHA256 1c336811b7b1ed9f6d9e69ec82b3075935f6bb8e5e127201d689394271ee00be SHA512 a5847e4e386fd22ca9ea595388e9539103f8dd3b26b7a4672c69b8b225490c66fee0df13c947529fcd07cf1411a881e69c1ce4eb7a217ae001275cb836b19cc1 WHIRLPOOL 6767bca53b8a46e80b77b170cf077e970ab4029d5fa03f56aa622225cb043b884d3d41b0f2618cb14f9f9b55182302719c73eb420b0f02a8ca6bff1c19b8dc5b
 MISC metadata.xml 280 SHA256 2a89088a60a3a553f10e587547ae1f20d6f9ef11a19adea0ee1f1bf64c7699b1 SHA512 872f8f6e475a90b03742078986ae1776e83c1c9f2cb7259c4e134b24e00990a81a9381921bd40e7fc5aeb3106c828dfa81f57969fd185866c44d285b991cc413 WHIRLPOOL f5974a759fda2aebc8e2954afba7172c5e8bc92d6e0fa5da48f2c7264bcec14e2f1114ae2db2cba40221457808b007102a29e6176f2cd335b997cd69b14827d8
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v2
+
+iQIcBAEBCAAGBQJUvsOsAAoJEGVpnaTzz9K9UdUQAILn3D8Dgv5AWy9s2gN/MAM8
+3WiWTD20BpJWYEb0rnTJhbK8SOXHjfqXTV7U9CFiS1qCzlj+yzhfqtXva/Tw/cWu
+jXj5Hrlmrx2oUELFr9vjie2TrVl6UeUSxqDQ7VAZUFOVOSnfX5UM3f0lNNl/Etxg
+lVNaoC3HScPuu+jTPofY5f0HOSHWORPLniPaGc1J0zQCmlSxUpR3teN6xT1W0t3K
+FebtZ49rsNAWo0b5dsrogUBhEGnOs+foQvDXYYtSoC3F9czXpx7gYTkfZuJjSvj4
+mLhTCVAsptftAVg2HB4KiHi5U9ukXzQ8OSFOqgTLl3kcnll7CkAbvxH+IVPrHR1f
+M66Ym7UJ1PWNz7imHE/HhNcyMYb6S4QU9+eSlzn3gejfIJwcHYMFL5J3th1+AVoM
+Qv7w6Dh9IAnIFH3bfD5aLjq3igqlB4FnFghbAL2llLQocxO8wQAlp8N1YQFM04Zd
+4fZaT5R268gXGO1KEHHnawW/Rq1yItgNROBz3T1daVH0PB0OklsbDaqq2HA1yOR1
+mmFRIX0Veh3c5jfq/gr/jeZhWbcSpBLhY6neAOJV7+IwbIvXXvU0wflQRkMWLSY7
+w0YHYd+5RLwtA9catY4hUBMrIuFWkCU20aV6UK4c5sG3RceG7CDuTFmPr4+aRUeX
+UYzLj3Hm5Q1Wz3lKu2J/
+=cWFU
+-----END PGP SIGNATURE-----
diff --git a/kde-base/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch b/kde-base/kwalletd/files/kwalletd-4.14.3-CVE-2013-7252.patch
new file mode 100644 (file)
index 0000000..9019e17
--- /dev/null
@@ -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-base/kwalletd/kwalletd-4.14.3-r1.ebuild b/kde-base/kwalletd/kwalletd-4.14.3-r1.ebuild
new file mode 100644 (file)
index 0000000..44ea2f0
--- /dev/null
@@ -0,0 +1,34 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/kde-base/kwalletd/kwalletd-4.14.3-r1.ebuild,v 1.1 2015/01/20 21:07:52 johu Exp $
+
+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
+}