KWallet

blowfish.cc
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2001 George Staikos <staikos@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8// FIXME: should we unroll some loops? Optimization can be done here.
9
10/* Implementation of 16 rounds blowfish as described in:
11 * _Applied_Cryptography_ (c) Bruce Schneier, 1996.
12 */
13
14#include "blowfish.h"
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19
20#include "blowfishtables.h"
21
22// DO NOT INCLUDE THIS. IT BREAKS KWALLET.
23// We need to live with -Wundef until someone really figures out the problem.
24//#include <QtCore/qglobal.h> // for Q_BYTE_ORDER and friends
25// Workaround for -Wundef
26#define Q_BIG_ENDIAN 1
27#define Q_BYTE_ORDER Q_BIG_ENDIAN
28
29BlowFish::BlowFish()
30{
31 _blksz = 8;
32 m_key = nullptr;
33 m_initialized = false;
34}
35
36bool BlowFish::init()
37{
38 // Initialize the sboxes
39 for (int i = 0; i < 256; i++) {
40 m_S[0][i] = ks0[i];
41 m_S[1][i] = ks1[i];
42 m_S[2][i] = ks2[i];
43 m_S[3][i] = ks3[i];
44 }
45
46 uint32_t datal = 0;
47 uint32_t datar = 0;
48 uint32_t data = 0;
49 int j = 0;
50
51 // Update the sboxes and pbox.
52 for (int i = 0; i < 18; i++) {
53 data = 0;
54 for (int k = 0; k < 4; ++k) {
55 data = (data << 8) | ((unsigned char *)m_key)[j++];
56 if (j >= m_keylen / 8) {
57 j = 0;
58 }
59 }
60 m_P[i] = P[i] ^ data;
61 }
62
63 for (int i = 0; i < 18; i += 2) {
64 encipher(&datal, &datar);
65 m_P[i] = datal;
66 m_P[i + 1] = datar;
67 }
68
69 for (int j = 0; j < 4; j++) {
70 for (int i = 0; i < 256; i += 2) {
71 encipher(&datal, &datar);
72 m_S[j][i] = datal;
73 m_S[j][i + 1] = datar;
74 }
75 }
76
77 // Nice code from gpg's implementation...
78 // check to see if the key is weak and return error if so
79 for (int i = 0; i < 255; i++) {
80 for (int j = i + 1; j < 256; j++) {
81 if ((m_S[0][i] == m_S[0][j]) || (m_S[1][i] == m_S[1][j]) ||
82 (m_S[2][i] == m_S[2][j]) || (m_S[3][i] == m_S[3][j])) {
83 return false;
84 }
85 }
86 }
87
88 m_initialized = true;
89
90 return true;
91}
92
93BlowFish::~BlowFish()
94{
95 delete[](unsigned char *)m_key;
96 m_key = nullptr;
97}
98
99int BlowFish::keyLen() const
100{
101 return 448;
102}
103
104bool BlowFish::variableKeyLen() const
105{
106 return true;
107}
108
109bool BlowFish::readyToGo() const
110{
111 return m_initialized;
112}
113
114bool BlowFish::setKey(void *key, int bitlength)
115{
116 if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) {
117 return false;
118 }
119
120 delete[](unsigned char *)m_key;
121
122 m_key = new unsigned char[bitlength / 8];
123 memcpy(m_key, key, bitlength / 8);
124 m_keylen = bitlength;
125
126 return init();
127}
128// clang-format off
129#if Q_BYTE_ORDER == Q_BIG_ENDIAN
130#define shuffle(x) do { \
131 uint32_t r = x; \
132 x = (r & 0xff000000) >> 24; \
133 x |= (r & 0x00ff0000) >> 8; \
134 x |= (r & 0x0000ff00) << 8; \
135 x |= (r & 0x000000ff) << 24; \
136 } while (0)
137#endif
138// clang-format on
139
140int BlowFish::encrypt(void *block, int len)
141{
142 uint32_t *d = (uint32_t *)block;
143
144 if (!m_initialized || len % _blksz != 0) {
145 return -1;
146 }
147
148 for (int i = 0; i < len / _blksz; i++) {
149#if Q_BYTE_ORDER == Q_BIG_ENDIAN
150 shuffle(*d);
151 shuffle(*(d + 1));
152#endif
153 encipher(d, d + 1);
154#if Q_BYTE_ORDER == Q_BIG_ENDIAN
155 shuffle(*d);
156 shuffle(*(d + 1));
157#endif
158 d += 2;
159 }
160
161 return len;
162}
163
164int BlowFish::decrypt(void *block, int len)
165{
166 uint32_t *d = (uint32_t *)block;
167
168 if (!m_initialized || len % _blksz != 0) {
169 return -1;
170 }
171
172 for (int i = 0; i < len / _blksz; i++) {
173#if Q_BYTE_ORDER == Q_BIG_ENDIAN
174 shuffle(*d);
175 shuffle(*(d + 1));
176#endif
177 decipher(d, d + 1);
178#if Q_BYTE_ORDER == Q_BIG_ENDIAN
179 shuffle(*d);
180 shuffle(*(d + 1));
181#endif
182 d += 2;
183 }
184
185 return len;
186}
187
188uint32_t BlowFish::F(uint32_t x)
189{
190 unsigned short a;
191 unsigned short b;
192 unsigned short c;
193 unsigned short d;
194 uint32_t y;
195
196 d = x & 0x000000ff;
197 x >>= 8;
198 c = x & 0x000000ff;
199 x >>= 8;
200 b = x & 0x000000ff;
201 x >>= 8;
202 a = x & 0x000000ff;
203
204 y = m_S[0][a] + m_S[1][b];
205 y ^= m_S[2][c];
206 y += m_S[3][d];
207
208 return y;
209}
210
211void BlowFish::encipher(uint32_t *xl, uint32_t *xr)
212{
213 uint32_t Xl = *xl;
214 uint32_t Xr = *xr;
215 uint32_t temp;
216
217 for (int i = 0; i < 16; ++i) {
218 Xl ^= m_P[i];
219 Xr ^= F(Xl);
220 // Exchange
221 temp = Xl; Xl = Xr; Xr = temp;
222 }
223
224 // Exchange
225 temp = Xl; Xl = Xr; Xr = temp;
226
227 Xr ^= m_P[16];
228 Xl ^= m_P[17];
229
230 *xl = Xl;
231 *xr = Xr;
232}
233
234void BlowFish::decipher(uint32_t *xl, uint32_t *xr)
235{
236 uint32_t Xl = *xl;
237 uint32_t Xr = *xr;
238 uint32_t temp;
239
240 for (int i = 17; i > 1; --i) {
241 Xl ^= m_P[i];
242 Xr ^= F(Xl);
243 // Exchange
244 temp = Xl; Xl = Xr; Xr = temp;
245 }
246
247 // Exchange
248 temp = Xl; Xl = Xr; Xr = temp;
249
250 Xr ^= m_P[1];
251 Xl ^= m_P[0];
252
253 *xl = Xl;
254 *xr = Xr;
255}
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:01:06 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.