kwalletd: use QCryptographicHash for SHA1 hashes

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-03-29 02:04:18 +03:00
parent 4f737d1dd2
commit 912c4d822e
8 changed files with 11 additions and 573 deletions

View file

@ -11,7 +11,6 @@ set(kwalletbackend_LIB_SRCS
blockcipher.cc blockcipher.cc
blowfish.cc blowfish.cc
cbc.cc cbc.cc
sha1.cc
kwalletentry.cc kwalletentry.cc
kwalletbackend.cc kwalletbackend.cc
backendpersisthandler.cpp backendpersisthandler.cpp

View file

@ -29,7 +29,6 @@
#include "backendpersisthandler.h" #include "backendpersisthandler.h"
#include "kwalletbackend.h" #include "kwalletbackend.h"
#include "blowfish.h" #include "blowfish.h"
#include "sha1.h"
#include "cbc.h" #include "cbc.h"
#include <gcrypt.h> #include <gcrypt.h>
@ -37,11 +36,12 @@
#define KWALLET_CIPHER_BLOWFISH_ECB 0 // this was the old KWALLET_CIPHER_BLOWFISH_CBC #define KWALLET_CIPHER_BLOWFISH_ECB 0 // this was the old KWALLET_CIPHER_BLOWFISH_CBC
#define KWALLET_CIPHER_3DES_CBC 1 // unsupported #define KWALLET_CIPHER_3DES_CBC 1 // unsupported
#define KWALLET_CIPHER_GPG 2 // unsupported
#define KWALLET_CIPHER_BLOWFISH_CBC 3 #define KWALLET_CIPHER_BLOWFISH_CBC 3
#define KWALLET_HASH_SHA1 0 #define KWALLET_HASH_SHA1 0 // fallback
#define KWALLET_HASH_MD5 1 // unsupported #define KWALLET_HASH_MD5 1 // unsupported
#define KWALLET_HASH_PBKDF2_SHA512 2 // used when using kwallet with pam or since 4.13 version #define KWALLET_HASH_PBKDF2_SHA512 2 // used since 4.13 version
namespace KWallet { namespace KWallet {
@ -142,11 +142,11 @@ int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& versio
} }
// calculate the hash of the file // calculate the hash of the file
SHA1 sha; QCryptographicHash sha(QCryptographicHash::Sha1);
BlowFish _bf; BlowFish _bf;
CipherBlockChain bf(&_bf); CipherBlockChain bf(&_bf);
sha.process(decrypted.data(), decrypted.size()); sha.addData(decrypted);
// prepend and append the random data // prepend and append the random data
QByteArray wholeFile; QByteArray wholeFile;
@ -181,7 +181,7 @@ int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& versio
wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)]; wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
} }
const char *hash = (const char *)sha.hash(); const QByteArray hash = sha.result();
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
wholeFile[(int)(newsize - 20 + i)] = hash[i]; wholeFile[(int)(newsize - 20 + i)] = hash[i];
} }
@ -300,9 +300,9 @@ int BlowfishPersistHandler::read(Backend* wb, QFile& db, WId)
} }
// compute the hash ourself // compute the hash ourself
SHA1 sha; QCryptographicHash sha(QCryptographicHash::Sha1);
sha.process(t, fsize); sha.addData(t, fsize);
const char *testhash = (const char *)sha.hash(); const QByteArray testhash = sha.result();
// compare hashes // compare hashes
int sz = encrypted.size(); int sz = encrypted.size();

View file

@ -35,7 +35,6 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include "blowfish.h" #include "blowfish.h"
#include "sha1.h"
#include "cbc.h" #include "cbc.h"
#include <gcrypt.h> #include <gcrypt.h>
@ -119,97 +118,6 @@ static int password2PBKDF2_SHA512(const QByteArray &password, QByteArray& hash,
return error; return error;
} }
// this should be SHA-512 for release probably
static int password2hash(const QByteArray& password, QByteArray& hash) {
SHA1 sha;
int shasz = sha.size() / 8;
assert(shasz >= 20);
QByteArray block1(shasz, 0);
sha.process(password.data(), qMin(password.size(), 16));
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
memcpy(block1.data(), sha.hash(), shasz);
sha.reset();
sha.process(block1.data(), shasz);
}
sha.reset();
if (password.size() > 16) {
sha.process(password.data() + 16, qMin(password.size() - 16, 16));
QByteArray block2(shasz, 0);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
memcpy(block2.data(), sha.hash(), shasz);
sha.reset();
sha.process(block2.data(), shasz);
}
sha.reset();
if (password.size() > 32) {
sha.process(password.data() + 32, qMin(password.size() - 32, 16));
QByteArray block3(shasz, 0);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
memcpy(block3.data(), sha.hash(), shasz);
sha.reset();
sha.process(block3.data(), shasz);
}
sha.reset();
if (password.size() > 48) {
sha.process(password.data() + 48, password.size() - 48);
QByteArray block4(shasz, 0);
// To make brute force take longer
for (int i = 0; i < 2000; i++) {
memcpy(block4.data(), sha.hash(), shasz);
sha.reset();
sha.process(block4.data(), shasz);
}
sha.reset();
// split 14/14/14/14
hash.resize(56);
memcpy(hash.data(), block1.data(), 14);
memcpy(hash.data() + 14, block2.data(), 14);
memcpy(hash.data() + 28, block3.data(), 14);
memcpy(hash.data() + 42, block4.data(), 14);
block4.fill(0);
} else {
// split 20/20/16
hash.resize(56);
memcpy(hash.data(), block1.data(), 20);
memcpy(hash.data() + 20, block2.data(), 20);
memcpy(hash.data() + 40, block3.data(), 16);
}
block3.fill(0);
} else {
// split 20/20
hash.resize(40);
memcpy(hash.data(), block1.data(), 20);
memcpy(hash.data() + 20, block2.data(), 20);
}
block2.fill(0);
} else {
// entirely block1
hash.resize(20);
memcpy(hash.data(), block1.data(), 20);
}
block1.fill(0);
return 0;
}
int Backend::deref() { int Backend::deref() {
if (--_ref < 0) { if (--_ref < 0) {
kDebug() << "refCount negative!"; kDebug() << "refCount negative!";
@ -636,11 +544,11 @@ void Backend::setPassword(const QByteArray &password) {
_passhash.fill(0); // empty just in case _passhash.fill(0); // empty just in case
BlowFish _bf; BlowFish _bf;
CipherBlockChain bf(&_bf); CipherBlockChain bf(&_bf);
_passhash.resize(bf.keyLen()/8);
_newPassHash.resize(bf.keyLen()/8); _newPassHash.resize(bf.keyLen()/8);
_newPassHash.fill(0); _newPassHash.fill(0);
password2hash(password, _passhash); // this should be SHA-512 for release probably
_passhash = QCryptographicHash::hash(password, QCryptographicHash::Sha1);
QByteArray salt; QByteArray salt;
QFile saltFile(KGlobal::dirs()->saveLocation("kwallet") + _name + ".salt"); QFile saltFile(KGlobal::dirs()->saveLocation("kwallet") + _name + ".salt");

View file

@ -174,7 +174,6 @@ private:
BackendCipherType _cipherType; // the kind of encryption used for this wallet BackendCipherType _cipherType; // the kind of encryption used for this wallet
friend class BlowfishPersistHandler; friend class BlowfishPersistHandler;
friend class GpgPersistHandler;
// open the wallet with the password already set. This is // open the wallet with the password already set. This is
// called internally by both open and openPreHashed. // called internally by both open and openPreHashed.

View file

@ -1,337 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2001 George Staikos <staikos@kde.org>
Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF
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 "sha1.h"
#include <config-kwalletbackend.h>
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h> /* For uintXX_t on Tru64 */
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <string.h>
// FIXME: this can be optimized to one instruction on most cpus.
#define rol(x,y) ((x << y) | (x >> (32-y)))
#define K1 0x5a827999L
#define K2 0x6ed9eba1L
#define K3 0x8f1bbcdcL
#define K4 0xca62c1d6L
#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) )
#define F2(x,y,z) ( x ^ y ^ z )
#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) )
#define F4(x,y,z) ( x ^ y ^ z )
#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \
^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \
, (x[i&0x0f] = (tm << 1) | (tm >> 31)))
#define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \
+ f(b, c, d) \
+ k \
+ m; \
b = rol(b, 30); \
} while(0)
SHA1::SHA1() {
_hashlen = 160;
_init = false;
reset();
}
int SHA1::reset() {
_h0 = 0x67452301;
_h1 = 0xefcdab89;
_h2 = 0x98badcfe;
_h3 = 0x10325476;
_h4 = 0xc3d2e1f0;
_nblocks = 0;
_count = 0;
memset(_buf, 0, 56); // clear the buffer
_init = true;
return 0;
}
int SHA1::size() const {
return _hashlen;
}
SHA1::~SHA1() {
}
void SHA1::transform(void *data) {
unsigned int a, b, c, d, e, tm;
unsigned int x[16];
unsigned char *_data = (unsigned char *)data;
a = _h0;
b = _h1;
c = _h2;
d = _h3;
e = _h4;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
memcpy(x, _data, 64);
#else
int i;
unsigned char *p2;
for (i = 0, p2 = (unsigned char *)x; i < 16; i++, p2 += 4) {
p2[3] = *_data++;
p2[2] = *_data++;
p2[1] = *_data++;
p2[0] = *_data++;
}
#endif
R(a, b, c, d, e, F1, K1, x[ 0]);
R(e, a, b, c, d, F1, K1, x[ 1]);
R(d, e, a, b, c, F1, K1, x[ 2]);
R(c, d, e, a, b, F1, K1, x[ 3]);
R(b, c, d, e, a, F1, K1, x[ 4]);
R(a, b, c, d, e, F1, K1, x[ 5]);
R(e, a, b, c, d, F1, K1, x[ 6]);
R(d, e, a, b, c, F1, K1, x[ 7]);
R(c, d, e, a, b, F1, K1, x[ 8]);
R(b, c, d, e, a, F1, K1, x[ 9]);
R(a, b, c, d, e, F1, K1, x[10]);
R(e, a, b, c, d, F1, K1, x[11]);
R(d, e, a, b, c, F1, K1, x[12]);
R(c, d, e, a, b, F1, K1, x[13]);
R(b, c, d, e, a, F1, K1, x[14]);
R(a, b, c, d, e, F1, K1, x[15]);
R(e, a, b, c, d, F1, K1, M(16));
R(d, e, a, b, c, F1, K1, M(17));
R(c, d, e, a, b, F1, K1, M(18));
R(b, c, d, e, a, F1, K1, M(19));
R(a, b, c, d, e, F2, K2, M(20));
R(e, a, b, c, d, F2, K2, M(21));
R(d, e, a, b, c, F2, K2, M(22));
R(c, d, e, a, b, F2, K2, M(23));
R(b, c, d, e, a, F2, K2, M(24));
R(a, b, c, d, e, F2, K2, M(25));
R(e, a, b, c, d, F2, K2, M(26));
R(d, e, a, b, c, F2, K2, M(27));
R(c, d, e, a, b, F2, K2, M(28));
R(b, c, d, e, a, F2, K2, M(29));
R(a, b, c, d, e, F2, K2, M(30));
R(e, a, b, c, d, F2, K2, M(31));
R(d, e, a, b, c, F2, K2, M(32));
R(c, d, e, a, b, F2, K2, M(33));
R(b, c, d, e, a, F2, K2, M(34));
R(a, b, c, d, e, F2, K2, M(35));
R(e, a, b, c, d, F2, K2, M(36));
R(d, e, a, b, c, F2, K2, M(37));
R(c, d, e, a, b, F2, K2, M(38));
R(b, c, d, e, a, F2, K2, M(39));
R(a, b, c, d, e, F3, K3, M(40));
R(e, a, b, c, d, F3, K3, M(41));
R(d, e, a, b, c, F3, K3, M(42));
R(c, d, e, a, b, F3, K3, M(43));
R(b, c, d, e, a, F3, K3, M(44));
R(a, b, c, d, e, F3, K3, M(45));
R(e, a, b, c, d, F3, K3, M(46));
R(d, e, a, b, c, F3, K3, M(47));
R(c, d, e, a, b, F3, K3, M(48));
R(b, c, d, e, a, F3, K3, M(49));
R(a, b, c, d, e, F3, K3, M(50));
R(e, a, b, c, d, F3, K3, M(51));
R(d, e, a, b, c, F3, K3, M(52));
R(c, d, e, a, b, F3, K3, M(53));
R(b, c, d, e, a, F3, K3, M(54));
R(a, b, c, d, e, F3, K3, M(55));
R(e, a, b, c, d, F3, K3, M(56));
R(d, e, a, b, c, F3, K3, M(57));
R(c, d, e, a, b, F3, K3, M(58));
R(b, c, d, e, a, F3, K3, M(59));
R(a, b, c, d, e, F4, K4, M(60));
R(e, a, b, c, d, F4, K4, M(61));
R(d, e, a, b, c, F4, K4, M(62));
R(c, d, e, a, b, F4, K4, M(63));
R(b, c, d, e, a, F4, K4, M(64));
R(a, b, c, d, e, F4, K4, M(65));
R(e, a, b, c, d, F4, K4, M(66));
R(d, e, a, b, c, F4, K4, M(67));
R(c, d, e, a, b, F4, K4, M(68));
R(b, c, d, e, a, F4, K4, M(69));
R(a, b, c, d, e, F4, K4, M(70));
R(e, a, b, c, d, F4, K4, M(71));
R(d, e, a, b, c, F4, K4, M(72));
R(c, d, e, a, b, F4, K4, M(73));
R(b, c, d, e, a, F4, K4, M(74));
R(a, b, c, d, e, F4, K4, M(75));
R(e, a, b, c, d, F4, K4, M(76));
R(d, e, a, b, c, F4, K4, M(77));
R(c, d, e, a, b, F4, K4, M(78));
R(b, c, d, e, a, F4, K4, M(79));
_h0 += a;
_h1 += b;
_h2 += c;
_h3 += d;
_h4 += e;
}
bool SHA1::readyToGo() const {
return _init;
}
int SHA1::process(const void *block, int len) {
if (!_init) {
return -1;
}
unsigned char *_block = (unsigned char *)block;
int cnt = 0;
// Flush the buffer before proceeding
if (_count == 64) {
transform(_buf);
_count = 0;
_nblocks++;
}
if (!_block) {
return 0;
}
if (_count) {
for (; len && _count < 64; --len, ++cnt) {
_buf[_count++] = *_block++;
}
process(0, 0); // flush the buffer if necessary
if (!len) {
return cnt;
}
}
while (len >= 64) {
transform(_block);
_count = 0;
_nblocks++;
len -= 64;
cnt += 64;
_block += 64;
}
for (; len && _count < 64; --len, ++cnt) {
_buf[_count++] = *_block++;
}
return cnt;
}
const unsigned char *SHA1::hash() {
unsigned int t, msb, lsb;
unsigned char *p;
if (!_init) {
return (unsigned char *)_buf;
}
process(0, 0);
msb = 0;
t = _nblocks;
if ((lsb = t << 6) < t) {
msb++;
}
msb += t >> 26;
t = lsb;
if ((lsb = t + _count) < t) {
msb++;
}
t = lsb;
if ((lsb = t << 3) < t) {
msb++;
}
msb += t >> 29;
_buf[_count++] = 0x80;
if (_count < 56) {
while (_count < 56) {
_buf[_count++] = 0;
}
} else {
while (_count < 64) {
_buf[_count++] = 0;
}
process(0, 0);
memset(_buf, 0, 56);
}
_buf[56] = msb >> 24;
_buf[57] = msb >> 16;
_buf[58] = msb >> 8;
_buf[59] = msb;
_buf[60] = lsb >> 24;
_buf[61] = lsb >> 16;
_buf[62] = lsb >> 8;
_buf[63] = lsb;
transform(_buf);
p = _buf;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
#define X(a) do { *(uint32_t *)p = _h##a; p += 4; } while (0)
#else
#define X(a) do { *p++ = _h##a >> 24; *p++ = _h##a >> 16; \
*p++ = _h##a >> 8; *p++ = _h##a; } while (0)
#endif
X(0);
X(1);
X(2);
X(3);
X(4);
#undef X
_init = false;
return (unsigned char *)_buf;
}

View file

@ -1,72 +0,0 @@
/* This file is part of the KDE project
Copyright (C) 2001 George Staikos <staikos@kde.org>
Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF
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 SHA1__KO_H
#define SHA1__KO_H
#include <kwallet_export.h>
/* @internal
*/
class KWALLETBACKEND_EXPORT SHA1 {
public:
SHA1();
~SHA1();
/*
* The number of bits in the hash generated.
*/
int size() const;
/*
* True if all settings are good and we are ready to hash.
*/
bool readyToGo() const;
/*
* Process a block of data for the hash function.
*/
int process(const void *block, int len);
/*
* Return the digest as a 20 byte array reference.
* Calling this makes readyToGo() == false.
*/
const unsigned char *hash();
/*
* Reset the digest so a new one can be calculated.
*/
int reset();
protected:
int _hashlen;
bool _init;
long _h0, _h1, _h2, _h3, _h4;
long _nblocks;
int _count;
unsigned char _buf[64];
void transform(void *data);
};
#endif

View file

@ -23,15 +23,3 @@ kde4_add_manual_test(testbf ${testbf_SRCS})
target_link_libraries(testbf ${KDE4_KDECORE_LIBS} kwalletbackend ) target_link_libraries(testbf ${KDE4_KDECORE_LIBS} kwalletbackend )
########### next target ###############
set(testsha_SRCS testsha.cpp )
kde4_add_manual_test(testsha ${testsha_SRCS})
target_link_libraries(testsha ${KDE4_KDECORE_LIBS} kwalletbackend )
########### install files ###############

View file

@ -1,47 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sha1.h"
int main() {
SHA1 *sha1;
unsigned char data[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
unsigned long et[] = {0x11223344};
int rc;
printf("%d: 0x11 == %d and 0x44 == %d\n", ((unsigned char *)et)[0],
0x11, 0x44);
sha1 = new SHA1();
if (!sha1->readyToGo()) {
printf("Error: not ready to go!\n");
return -1;
}
printf("About to process [%s]\n", data);
rc = sha1->process(data, strlen((char *)data));
if (rc != strlen((char *)data)) {
printf("Error processing the data. rc=%d\n", rc);
return -1;
} else printf("Done.\n");
const unsigned char *res = sha1->hash();
if (res) {
for (int i = 0; i < 20; i++) {
printf("%.2X", *res++);
if (i>0 && (i-1)%2 == 0) printf(" ");
}
printf("\n");
} else {
printf("Error - getHash() returned NULL!\n");
return -1;
}
delete sha1;
}