add more spacing
[personal-kdebase.git] / runtime / kwalletd / backend / blowfish.cc
bloba2490242ae536034210604ffdebb6851704c6ecc
1 /* This file is part of the KDE project
2 Copyright (C) 2001 George Staikos <staikos@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 // FIXME: should we unroll some loops? Optimization can be done here.
24 /* Implementation of 16 rounds blowfish as described in:
25 * _Applied_Cryptography_ (c) Bruce Schneier, 1996.
28 #include "blowfish.h"
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <QtCore/QBool>
35 #include "blowfishtables.h"
38 BlowFish::BlowFish() {
39 _blksz = 8;
40 _key = 0L;
41 _init = false;
46 bool BlowFish::init() {
47 // Initialize the sboxes
48 for (int i = 0; i < 256; i++) {
49 _S[0][i] = ks0[i];
50 _S[1][i] = ks1[i];
51 _S[2][i] = ks2[i];
52 _S[3][i] = ks3[i];
55 uint32_t datal = 0;
56 uint32_t datar = 0;
57 uint32_t data = 0;
58 int j = 0;
61 // Update the sboxes and pbox.
62 for (int i = 0; i < 18; i++) {
63 data = 0;
64 for (int k = 0; k < 4; ++k) {
65 data = (data << 8) | ((unsigned char *)_key)[j++];
66 if (j >= _keylen / 8) {
67 j = 0;
70 _P[i] = P[i] ^ data;
73 for (int i = 0; i < 18; i += 2) {
74 encipher(&datal, &datar);
75 _P[i] = datal;
76 _P[i+1] = datar;
79 for (int j = 0; j < 4; j++) {
80 for (int i = 0; i < 256; i += 2) {
81 encipher(&datal, &datar);
82 _S[j][i] = datal;
83 _S[j][i+1] = datar;
87 // Nice code from gpg's implementation...
88 // check to see if the key is weak and return error if so
89 for (int i = 0; i < 255; i++) {
90 for (int j = i + 1; j < 256; j++) {
91 if ((_S[0][i] == _S[0][j]) || (_S[1][i] == _S[1][j]) ||
92 (_S[2][i] == _S[2][j]) || (_S[3][i] == _S[3][j])) {
93 return false;
98 _init = true;
100 return true;
104 BlowFish::~BlowFish() {
105 delete[] (unsigned char *)_key;
106 _key = 0L;
110 int BlowFish::keyLen() const {
111 return 448;
115 bool BlowFish::variableKeyLen() const {
116 return true;
120 bool BlowFish::readyToGo() const {
121 return _init;
125 bool BlowFish::setKey(void *key, int bitlength) {
126 if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) {
127 return false;
130 delete[] (unsigned char *)_key;
132 _key = new unsigned char[bitlength / 8];
133 memcpy(_key, key, bitlength / 8);
134 _keylen = bitlength;
136 return init();
140 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
141 #define shuffle(x) do { \
142 uint32_t r = x; \
143 x = (r & 0xff000000) >> 24; \
144 x |= (r & 0x00ff0000) >> 8; \
145 x |= (r & 0x0000ff00) << 8; \
146 x |= (r & 0x000000ff) << 24; \
147 } while (0)
148 #endif
150 int BlowFish::encrypt(void *block, int len) {
151 uint32_t *d = (uint32_t *)block;
153 if (!_init || len % _blksz != 0) {
154 return -1;
157 for (int i = 0; i < len / _blksz; i++) {
158 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
159 shuffle(*d);
160 shuffle(*(d + 1));
161 #endif
162 encipher(d, d + 1);
163 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
164 shuffle(*d);
165 shuffle(*(d + 1));
166 #endif
167 d += 2;
170 return len;
174 int BlowFish::decrypt(void *block, int len) {
175 uint32_t *d = (uint32_t *)block;
177 if (!_init || len % _blksz != 0) {
178 return -1;
181 for (int i = 0; i < len / _blksz; i++) {
182 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
183 shuffle(*d);
184 shuffle(*(d + 1));
185 #endif
186 decipher(d, d + 1);
187 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
188 shuffle(*d);
189 shuffle(*(d + 1));
190 #endif
191 d += 2;
194 return len;
198 uint32_t BlowFish::F(uint32_t x) {
199 unsigned short a, b, c, d;
200 uint32_t y;
202 d = x & 0x000000ff;
203 x >>= 8;
204 c = x & 0x000000ff;
205 x >>= 8;
206 b = x & 0x000000ff;
207 x >>= 8;
208 a = x & 0x000000ff;
210 y = _S[0][a] + _S[1][b];
211 y ^= _S[2][c];
212 y += _S[3][d];
214 return y;
218 void BlowFish::encipher(uint32_t *xl, uint32_t *xr) {
219 uint32_t Xl = *xl, Xr = *xr, temp;
221 for (int i = 0; i < 16; ++i) {
222 Xl ^= _P[i];
223 Xr ^= F(Xl);
224 // Exchange
225 temp = Xl; Xl = Xr; Xr = temp;
228 // Exchange
229 temp = Xl; Xl = Xr; Xr = temp;
231 Xr ^= _P[16];
232 Xl ^= _P[17];
234 *xl = Xl;
235 *xr = Xr;
239 void BlowFish::decipher(uint32_t *xl, uint32_t *xr) {
240 uint32_t Xl = *xl, Xr = *xr, temp;
242 for (int i = 17; i > 1; --i) {
243 Xl ^= _P[i];
244 Xr ^= F(Xl);
245 // Exchange
246 temp = Xl; Xl = Xr; Xr = temp;
249 // Exchange
250 temp = Xl; Xl = Xr; Xr = temp;
252 Xr ^= _P[1];
253 Xl ^= _P[0];
255 *xl = Xl;
256 *xr = Xr;