File indexing completed on 2024-06-16 03:53:03
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2001 George Staikos <staikos@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "cbc.h" 0009 #include "kwalletbackend_debug.h" 0010 #include <string.h> 0011 0012 CipherBlockChain::CipherBlockChain(BlockCipher *cipher, bool useECBforReading) : 0013 _cipher(cipher) 0014 , _useECBforReading(useECBforReading) 0015 { 0016 _next = nullptr; 0017 _register = nullptr; 0018 _len = -1; 0019 _reader = _writer = 0L; 0020 if (cipher) { 0021 _blksz = cipher->blockSize(); 0022 } 0023 } 0024 0025 CipherBlockChain::~CipherBlockChain() 0026 { 0027 delete[](char *)_register; 0028 _register = nullptr; 0029 delete[](char *)_next; 0030 _next = nullptr; 0031 } 0032 0033 bool CipherBlockChain::setKey(void *key, int bitlength) 0034 { 0035 if (_cipher) { 0036 return _cipher->setKey(key, bitlength); 0037 } 0038 return false; 0039 } 0040 0041 int CipherBlockChain::keyLen() const 0042 { 0043 if (_cipher) { 0044 return _cipher->keyLen(); 0045 } 0046 return -1; 0047 } 0048 0049 bool CipherBlockChain::variableKeyLen() const 0050 { 0051 if (_cipher) { 0052 return _cipher->variableKeyLen(); 0053 } 0054 return false; 0055 } 0056 0057 bool CipherBlockChain::readyToGo() const 0058 { 0059 if (_cipher) { 0060 return _cipher->readyToGo(); 0061 } 0062 return false; 0063 } 0064 0065 void CipherBlockChain::initRegister() { 0066 if (_register == nullptr) { 0067 size_t registerLen = _cipher->blockSize(); 0068 _register = new unsigned char[registerLen]; 0069 _len = registerLen; 0070 } 0071 memset(_register, 0, _len); 0072 } 0073 0074 int CipherBlockChain::encrypt(void *block, int len) 0075 { 0076 if (_cipher && !_reader) { 0077 int rc; 0078 0079 _writer |= 1; 0080 0081 initRegister(); 0082 0083 if ((len % _len) >0) { 0084 qCDebug(KWALLETBACKEND_LOG) << "Block length given encrypt (" << len << ") is not a multiple of " << _len; 0085 return -1; 0086 } 0087 0088 char *elemBlock = static_cast<char*>(block); 0089 for (int b = 0; b < len/_len; b++) { 0090 0091 // This might be optimizable 0092 char *tb = static_cast<char*>(elemBlock); 0093 for (int i = 0; i < _len; i++) { 0094 *tb++ ^= ((char *)_register)[i]; 0095 } 0096 0097 rc = _cipher->encrypt(elemBlock, _len); 0098 0099 if (rc != -1) { 0100 memcpy(_register, elemBlock, _len); 0101 } 0102 elemBlock += _len; 0103 } 0104 0105 return rc; 0106 } 0107 return -1; 0108 } 0109 0110 // This is the old decrypt method, that was decrypting using ECB 0111 // instead of CBC 0112 int CipherBlockChain::decryptECB(void *block, int len) { 0113 if (_cipher && !_writer) { 0114 int rc; 0115 0116 _reader |= 1; 0117 0118 if (!_register) { 0119 _register = new unsigned char[len]; 0120 _len = len; 0121 memset(_register, 0, len); 0122 } else if (len > _len) { 0123 return -1; 0124 } 0125 0126 if (!_next) { 0127 _next = new unsigned char[_len]; 0128 } 0129 memcpy(_next, block, _len); 0130 0131 rc = _cipher->decrypt(block, len); 0132 0133 if (rc != -1) { 0134 // This might be optimizable 0135 char *tb = (char *)block; 0136 for (int i = 0; i < len; i++) { 0137 tb[i] ^= ((char *)_register)[i]; 0138 } 0139 } 0140 0141 void *temp; 0142 temp = _next; 0143 _next = _register; 0144 _register = temp; 0145 0146 return rc; 0147 } 0148 return -1; 0149 } 0150 0151 int CipherBlockChain::decrypt(void *block, int len) 0152 { 0153 if (_useECBforReading) { 0154 qCDebug(KWALLETBACKEND_LOG) << "decrypting using ECB!"; 0155 return decryptECB(block, len); 0156 } 0157 0158 if (_cipher && !_writer) { 0159 int rc = 0; 0160 0161 _reader |= 1; 0162 0163 initRegister(); 0164 0165 if ((len % _len) >0) { 0166 qCDebug(KWALLETBACKEND_LOG) << "Block length given for decrypt (" << len << ") is not a multiple of " << _len; 0167 return -1; 0168 } 0169 0170 char *elemBlock = static_cast<char*>(block); 0171 for (int b = 0; b < len/_len; b++) { 0172 if (_next == nullptr) { 0173 _next = new unsigned char[_len]; 0174 } 0175 memcpy(_next, elemBlock, _len); 0176 0177 int bytesDecrypted = _cipher->decrypt(elemBlock, _len); 0178 0179 if (bytesDecrypted != -1) { 0180 rc += bytesDecrypted; 0181 // This might be optimizable 0182 char *tb = (char *)elemBlock; 0183 for (int i = 0; i < _len; i++) { 0184 *tb++ ^= ((char *)_register)[i]; 0185 } 0186 } 0187 0188 void *temp; 0189 temp = _next; 0190 _next = _register; 0191 _register = temp; 0192 0193 elemBlock += _len; 0194 } 0195 0196 return rc; 0197 } 0198 return -1; 0199 } 0200