File indexing completed on 2024-06-16 03:53:04

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 <string.h>
0010 
0011 CipherBlockChain::CipherBlockChain(BlockCipher *cipher) : _cipher(cipher)
0012 {
0013     _next = 0L;
0014     _register = 0L;
0015     _len = -1;
0016     _reader = _writer = 0L;
0017     if (cipher) {
0018         _blksz = cipher->blockSize();
0019     }
0020 }
0021 
0022 CipherBlockChain::~CipherBlockChain()
0023 {
0024     delete[](char *)_register;
0025     _register = 0L;
0026     delete[](char *)_next;
0027     _next = 0L;
0028 }
0029 
0030 bool CipherBlockChain::setKey(void *key, int bitlength)
0031 {
0032     if (_cipher) {
0033         return _cipher->setKey(key, bitlength);
0034     }
0035     return false;
0036 }
0037 
0038 int CipherBlockChain::keyLen() const
0039 {
0040     if (_cipher) {
0041         return _cipher->keyLen();
0042     }
0043     return -1;
0044 }
0045 
0046 bool CipherBlockChain::variableKeyLen() const
0047 {
0048     if (_cipher) {
0049         return _cipher->variableKeyLen();
0050     }
0051     return false;
0052 }
0053 
0054 bool CipherBlockChain::readyToGo() const
0055 {
0056     if (_cipher) {
0057         return _cipher->readyToGo();
0058     }
0059     return false;
0060 }
0061 
0062 int CipherBlockChain::encrypt(void *block, int len)
0063 {
0064     if (_cipher && !_reader) {
0065         int rc;
0066 
0067         _writer |= 1;
0068 
0069         if (!_register) {
0070             _register = new unsigned char[len];
0071             _len = len;
0072             memset(_register, 0, len);
0073         } else if (len > _len) {
0074             return -1;
0075         }
0076 
0077         // This might be optimizable
0078         char *tb = (char *)block;
0079         for (int i = 0; i < len; i++) {
0080             tb[i] ^= ((char *)_register)[i];
0081         }
0082 
0083         rc = _cipher->encrypt(block, len);
0084 
0085         if (rc != -1) {
0086             memcpy(_register, block, len);
0087         }
0088 
0089         return rc;
0090     }
0091     return -1;
0092 }
0093 
0094 int CipherBlockChain::decrypt(void *block, int len)
0095 {
0096     if (_cipher && !_writer) {
0097         int rc;
0098 
0099         _reader |= 1;
0100 
0101         if (!_register) {
0102             _register = new unsigned char[len];
0103             _len = len;
0104             memset(_register, 0, len);
0105         } else if (len > _len) {
0106             return -1;
0107         }
0108 
0109         if (!_next) {
0110             _next = new unsigned char[_len];
0111         }
0112         memcpy(_next, block, _len);
0113 
0114         rc = _cipher->decrypt(block, len);
0115 
0116         if (rc != -1) {
0117             // This might be optimizable
0118             char *tb = (char *)block;
0119             for (int i = 0; i < len; i++) {
0120                 tb[i] ^= ((char *)_register)[i];
0121             }
0122         }
0123 
0124         void *temp;
0125         temp = _next;
0126         _next = _register;
0127         _register = temp;
0128 
0129         return rc;
0130     }
0131     return -1;
0132 }
0133