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 // FIXME: should we unroll some loops? Optimization can be done here. 0009 0010 /* Implementation of 16 rounds blowfish as described in: 0011 * _Applied_Cryptography_ (c) Bruce Schneier, 1996. 0012 */ 0013 0014 #include "blowfish.h" 0015 0016 #include <stdlib.h> 0017 #include <stdio.h> 0018 #include <string.h> 0019 0020 #include "blowfishtables.h" 0021 0022 // DO NOT INCLUDE THIS. IT BREAKS KWALLET. 0023 // We need to live with -Wundef until someone really figures out the problem. 0024 //#include <QtCore/qglobal.h> // for Q_BYTE_ORDER and friends 0025 // Workaround for -Wundef 0026 #define Q_BIG_ENDIAN 1 0027 #define Q_BYTE_ORDER Q_BIG_ENDIAN 0028 0029 BlowFish::BlowFish() 0030 { 0031 _blksz = 8; 0032 m_key = nullptr; 0033 m_initialized = false; 0034 } 0035 0036 bool BlowFish::init() 0037 { 0038 // Initialize the sboxes 0039 for (int i = 0; i < 256; i++) { 0040 m_S[0][i] = ks0[i]; 0041 m_S[1][i] = ks1[i]; 0042 m_S[2][i] = ks2[i]; 0043 m_S[3][i] = ks3[i]; 0044 } 0045 0046 uint32_t datal = 0; 0047 uint32_t datar = 0; 0048 uint32_t data = 0; 0049 int j = 0; 0050 0051 // Update the sboxes and pbox. 0052 for (int i = 0; i < 18; i++) { 0053 data = 0; 0054 for (int k = 0; k < 4; ++k) { 0055 data = (data << 8) | ((unsigned char *)m_key)[j++]; 0056 if (j >= m_keylen / 8) { 0057 j = 0; 0058 } 0059 } 0060 m_P[i] = P[i] ^ data; 0061 } 0062 0063 for (int i = 0; i < 18; i += 2) { 0064 encipher(&datal, &datar); 0065 m_P[i] = datal; 0066 m_P[i + 1] = datar; 0067 } 0068 0069 for (int j = 0; j < 4; j++) { 0070 for (int i = 0; i < 256; i += 2) { 0071 encipher(&datal, &datar); 0072 m_S[j][i] = datal; 0073 m_S[j][i + 1] = datar; 0074 } 0075 } 0076 0077 // Nice code from gpg's implementation... 0078 // check to see if the key is weak and return error if so 0079 for (int i = 0; i < 255; i++) { 0080 for (int j = i + 1; j < 256; j++) { 0081 if ((m_S[0][i] == m_S[0][j]) || (m_S[1][i] == m_S[1][j]) || 0082 (m_S[2][i] == m_S[2][j]) || (m_S[3][i] == m_S[3][j])) { 0083 return false; 0084 } 0085 } 0086 } 0087 0088 m_initialized = true; 0089 0090 return true; 0091 } 0092 0093 BlowFish::~BlowFish() 0094 { 0095 delete[](unsigned char *)m_key; 0096 m_key = nullptr; 0097 } 0098 0099 int BlowFish::keyLen() const 0100 { 0101 return 448; 0102 } 0103 0104 bool BlowFish::variableKeyLen() const 0105 { 0106 return true; 0107 } 0108 0109 bool BlowFish::readyToGo() const 0110 { 0111 return m_initialized; 0112 } 0113 0114 bool BlowFish::setKey(void *key, int bitlength) 0115 { 0116 if (bitlength <= 0 || bitlength > 448 || bitlength % 8 != 0) { 0117 return false; 0118 } 0119 0120 delete[](unsigned char *)m_key; 0121 0122 m_key = new unsigned char[bitlength / 8]; 0123 memcpy(m_key, key, bitlength / 8); 0124 m_keylen = bitlength; 0125 0126 return init(); 0127 } 0128 // clang-format off 0129 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0130 #define shuffle(x) do { \ 0131 uint32_t r = x; \ 0132 x = (r & 0xff000000) >> 24; \ 0133 x |= (r & 0x00ff0000) >> 8; \ 0134 x |= (r & 0x0000ff00) << 8; \ 0135 x |= (r & 0x000000ff) << 24; \ 0136 } while (0) 0137 #endif 0138 // clang-format on 0139 0140 int BlowFish::encrypt(void *block, int len) 0141 { 0142 uint32_t *d = (uint32_t *)block; 0143 0144 if (!m_initialized || len % _blksz != 0) { 0145 return -1; 0146 } 0147 0148 for (int i = 0; i < len / _blksz; i++) { 0149 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0150 shuffle(*d); 0151 shuffle(*(d + 1)); 0152 #endif 0153 encipher(d, d + 1); 0154 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0155 shuffle(*d); 0156 shuffle(*(d + 1)); 0157 #endif 0158 d += 2; 0159 } 0160 0161 return len; 0162 } 0163 0164 int BlowFish::decrypt(void *block, int len) 0165 { 0166 uint32_t *d = (uint32_t *)block; 0167 0168 if (!m_initialized || len % _blksz != 0) { 0169 return -1; 0170 } 0171 0172 for (int i = 0; i < len / _blksz; i++) { 0173 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0174 shuffle(*d); 0175 shuffle(*(d + 1)); 0176 #endif 0177 decipher(d, d + 1); 0178 #if Q_BYTE_ORDER == Q_BIG_ENDIAN 0179 shuffle(*d); 0180 shuffle(*(d + 1)); 0181 #endif 0182 d += 2; 0183 } 0184 0185 return len; 0186 } 0187 0188 uint32_t BlowFish::F(uint32_t x) 0189 { 0190 unsigned short a; 0191 unsigned short b; 0192 unsigned short c; 0193 unsigned short d; 0194 uint32_t y; 0195 0196 d = x & 0x000000ff; 0197 x >>= 8; 0198 c = x & 0x000000ff; 0199 x >>= 8; 0200 b = x & 0x000000ff; 0201 x >>= 8; 0202 a = x & 0x000000ff; 0203 0204 y = m_S[0][a] + m_S[1][b]; 0205 y ^= m_S[2][c]; 0206 y += m_S[3][d]; 0207 0208 return y; 0209 } 0210 0211 void BlowFish::encipher(uint32_t *xl, uint32_t *xr) 0212 { 0213 uint32_t Xl = *xl; 0214 uint32_t Xr = *xr; 0215 uint32_t temp; 0216 0217 for (int i = 0; i < 16; ++i) { 0218 Xl ^= m_P[i]; 0219 Xr ^= F(Xl); 0220 // Exchange 0221 temp = Xl; Xl = Xr; Xr = temp; 0222 } 0223 0224 // Exchange 0225 temp = Xl; Xl = Xr; Xr = temp; 0226 0227 Xr ^= m_P[16]; 0228 Xl ^= m_P[17]; 0229 0230 *xl = Xl; 0231 *xr = Xr; 0232 } 0233 0234 void BlowFish::decipher(uint32_t *xl, uint32_t *xr) 0235 { 0236 uint32_t Xl = *xl; 0237 uint32_t Xr = *xr; 0238 uint32_t temp; 0239 0240 for (int i = 17; i > 1; --i) { 0241 Xl ^= m_P[i]; 0242 Xr ^= F(Xl); 0243 // Exchange 0244 temp = Xl; Xl = Xr; Xr = temp; 0245 } 0246 0247 // Exchange 0248 temp = Xl; Xl = Xr; Xr = temp; 0249 0250 Xr ^= m_P[1]; 0251 Xl ^= m_P[0]; 0252 0253 *xl = Xl; 0254 *xr = Xr; 0255 }