1 /*****************************************************************************\
3 * Name : blowfish encryption *
4 * Author : Chris Koeritz *
6 *******************************************************************************
7 * Copyright (c) 2005-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
15 #include "blowfish_crypto.h"
18 #include <basis/astring.h>
19 #include <basis/functions.h>
20 #include <basis/mutex.h>
21 #include <loggers/critical_events.h>
22 #include <loggers/program_wide_logger.h>
23 #include <mathematics/chaos.h>
24 #include <structures/static_memory_gremlin.h>
26 #include <openssl/blowfish.h>
27 #include <openssl/evp.h>
29 using namespace basis;
30 using namespace loggers;
31 using namespace mathematics;
32 using namespace structures;
36 const int FUDGE = 128;
37 // extra space for the cipher's block size. blowfish is only 8 bytes for
38 // the cipher block size, but we ensure there will definitely be no
42 // get rid of a macro we don't want.
45 #define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t)
47 //#define DEBUG_BLOWFISH
48 // uncomment for noisier version.
51 // this macro checks on the validity of the key sizes (in bits).
52 #define DISCUSS_KEY_SIZE(key_size) \
53 if (key_size < minimum_key_size()) { \
54 continuable_error(static_class_name(), func, \
55 a_sprintf("key size (%d bits) is less than minimum key size %d.", \
56 key_size, minimum_key_size())); \
58 if (key_size > maximum_key_size()) { \
59 continuable_error(static_class_name(), func, \
60 a_sprintf("key size (%d bits) is greater than maximum key size %d.", \
61 key_size, maximum_key_size())); \
64 // this macro checks that the key in the byte array has enough bytes for
66 #define DISCUSS_PROVIDED_KEY(key_size, key) \
67 if (key.length() * BITS_PER_BYTE < key_size) { \
68 continuable_error(static_class_name(), func, \
69 a_sprintf("key array length (%d) is less than required by key size " \
70 "(%d bits).", key.length(), key_size)); \
73 #define DISCUSS_PROVIDED_KEY(key_size, key)
74 #define DISCUSS_KEY_SIZE(key_size)
77 blowfish_crypto::blowfish_crypto(int key_size)
78 : _key_size(key_size),
81 // FUNCDEF("constructor [int]");
82 static_ssl_initializer();
83 DISCUSS_KEY_SIZE(key_size);
84 if (key_size < minimum_key_size())
85 _key_size = minimum_key_size();
86 if (key_size > maximum_key_size())
87 _key_size = maximum_key_size();
88 generate_key(_key_size, *_key);
91 blowfish_crypto::blowfish_crypto(const byte_array &key, int key_size)
92 : _key_size(key_size),
93 _key(new byte_array(key))
95 // FUNCDEF("constructor [byte_array/int]");
96 // any problems with the key provided are horrid. they will yield a
97 // non-working blowfish object.
98 DISCUSS_KEY_SIZE(key_size);
99 DISCUSS_PROVIDED_KEY(key_size, key);
100 static_ssl_initializer();
103 blowfish_crypto::blowfish_crypto(const blowfish_crypto &to_copy)
105 _key_size(to_copy._key_size),
106 _key(new byte_array(*to_copy._key))
107 { static_ssl_initializer(); }
109 blowfish_crypto::~blowfish_crypto()
114 int blowfish_crypto::key_size() const { return _key_size; }
116 const byte_array &blowfish_crypto::get_key() const { return *_key; }
118 int blowfish_crypto::minimum_key_size() { return 64; }
120 int blowfish_crypto::maximum_key_size() { return 448; }
122 blowfish_crypto &blowfish_crypto::operator = (const blowfish_crypto &to_copy)
124 if (this == &to_copy) return *this;
125 _key_size = to_copy._key_size;
126 *_key = *to_copy._key;
130 bool blowfish_crypto::set_key(const byte_array &new_key, int key_size)
132 // FUNCDEF("set_key");
133 if (!new_key.length()) return false;
134 DISCUSS_KEY_SIZE(key_size);
135 DISCUSS_PROVIDED_KEY(key_size, new_key);
136 if ( (key_size < minimum_key_size()) || (key_size > maximum_key_size()) )
138 if (new_key.length() * BITS_PER_BYTE < key_size) return false;
139 _key_size = key_size;
144 void blowfish_crypto::generate_key(int size, byte_array &new_key)
146 // FUNCDEF("generate_key");
147 DISCUSS_KEY_SIZE(size);
148 if (size < minimum_key_size())
149 size = minimum_key_size();
150 else if (size > maximum_key_size())
151 size = maximum_key_size();
152 int bytes = size / BITS_PER_BYTE; // calculate the number of bytes needed.
153 if (size % BITS_PER_BYTE) bytes++; // add one for non-integral portion.
154 new_key.reset(bytes);
155 for (int i = 0; i < bytes; i++)
156 new_key[i] = static_ssl_initializer().randomizer().inclusive(0, 255);
159 SAFE_STATIC(mutex, __vector_init_lock, )
161 const byte_array &blowfish_crypto::init_vector()
163 auto_synchronizer locking(__vector_init_lock());
164 static byte_array to_return(EVP_MAX_IV_LENGTH);
165 static bool initted = false;
167 for (int i = 0; i < EVP_MAX_IV_LENGTH; i++)
168 to_return[i] = 214 - i;
174 bool blowfish_crypto::encrypt(const byte_array &source,
175 byte_array &target) const
179 if (!_key->length() || !source.length()) return false;
180 bool to_return = true;
182 // initialize an encoding session.
183 EVP_CIPHER_CTX session;
184 EVP_CIPHER_CTX_init(&session);
185 EVP_EncryptInit_ex(&session, EVP_bf_cbc(), NIL, _key->observe(),
186 init_vector().observe());
187 EVP_CIPHER_CTX_set_key_length(&session, _key_size);
189 // allocate temporary space for encrypted data.
190 byte_array encoded(source.length() + FUDGE);
192 // encrypt the entire source buffer.
194 int enc_ret = EVP_EncryptUpdate(&session, encoded.access(), &encoded_len,
195 source.observe(), source.length());
197 continuable_error(class_name(), func, a_sprintf("encryption failed, "
198 "result=%d.", enc_ret));
201 // chop any extra space off.
202 // LOG(a_sprintf("encrypting bytes %d to %d.\n", i, edge));
203 encoded.zap(encoded_len, encoded.last());
207 // only add padding if we succeeded with the encryption.
209 // finalize the encryption.
210 encoded.reset(FUDGE); // reinflate for padding.
212 enc_ret = EVP_EncryptFinal_ex(&session, encoded.access(), &pad_len);
214 continuable_error(class_name(), func, a_sprintf("finalizing encryption "
215 "failed, result=%d.", enc_ret));
218 // LOG(a_sprintf("padding added %d bytes.\n", pad_len));
219 encoded.zap(pad_len, encoded.last());
224 EVP_CIPHER_CTX_cleanup(&session);
228 bool blowfish_crypto::decrypt(const byte_array &source,
229 byte_array &target) const
233 if (!_key->length() || !source.length()) return false;
234 bool to_return = true;
235 EVP_CIPHER_CTX session;
236 EVP_CIPHER_CTX_init(&session);
237 //LOG(a_sprintf("key size %d bits.\n", BITS_PER_BYTE * _key->length()));
238 EVP_DecryptInit_ex(&session, EVP_bf_cbc(), NIL, _key->observe(),
239 init_vector().observe());
240 EVP_CIPHER_CTX_set_key_length(&session, _key_size);
242 // allocate enough space for decoded bytes.
243 byte_array decoded(source.length() + FUDGE);
246 int dec_ret = EVP_DecryptUpdate(&session, decoded.access(), &decoded_len,
247 source.observe(), source.length());
249 continuable_error(class_name(), func, "decryption failed.");
252 // LOG(a_sprintf(" decrypted size in bytes is %d.\n", decoded_len));
253 decoded.zap(decoded_len, decoded.last());
257 // only process padding if the first part of decryption succeeded.
259 decoded.reset(FUDGE); // reinflate for padding.
261 dec_ret = EVP_DecryptFinal_ex(&session, decoded.access(), &pad_len);
262 // LOG(a_sprintf("padding added %d bytes.\n", pad_len));
264 continuable_error(class_name(), func, a_sprintf("finalizing decryption "
265 "failed, result=%d, padlen=%d, target had %d bytes.", dec_ret,
266 pad_len, target.length()));
269 int dec_size = pad_len;
270 decoded.zap(dec_size, decoded.last());
275 EVP_CIPHER_CTX_cleanup(&session);