kde-workspace/kwalletd/backend/cbc.cc
Ivailo Monev 91780aff84 kwalletd: remove ECB support
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
2021-03-29 13:29:54 +03:00

157 lines
3.8 KiB
C++

/* 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>
#include <kdebug.h>
CipherBlockChain::CipherBlockChain(BlockCipher *cipher)
: _cipher(cipher)
{
_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;
}
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;
}
bool CipherBlockChain::readyToGo() const
{
if (_cipher) {
return _cipher->readyToGo();
}
return false;
}
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)
{
int rc = -1;
if (_cipher && !_reader) {
_writer |= 1;
initRegister();
if ((len % _len) >0) {
kDebug() << "Block length given encrypt (" << len << ") is not a multiple of " << _len;
return -1;
}
char *elemBlock = static_cast<char*>(block);
for (int b = 0; b < len/_len; b++) {
// This might be optimizable
char *tb = static_cast<char*>(elemBlock);
for (int i = 0; i < _len; i++) {
*tb++ ^= ((char *)_register)[i];
}
rc = _cipher->encrypt(elemBlock, _len);
if (rc != -1) {
memcpy(_register, elemBlock, _len);
}
elemBlock += _len;
}
return rc;
}
return rc;
}
int CipherBlockChain::decrypt(void *block, int 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;
}