00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef lint
00024 static const char rcsid[] = "$Id: blowfish.c,v 1.18 2004-06-23 11:19:52 wingman Exp $";
00025 #endif
00026
00027 #include <sys/types.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include <eggdrop/eggdrop.h>
00032
00033 #include "blowfish.h"
00034 #include "bf_tab.h"
00035
00036 #define start blowfish_LTX_start
00037
00038
00039 #define BOXES 3
00040
00041
00042 #define S0(x) (bf_S[0][x.w.byte0])
00043 #define S1(x) (bf_S[1][x.w.byte1])
00044 #define S2(x) (bf_S[2][x.w.byte2])
00045 #define S3(x) (bf_S[3][x.w.byte3])
00046 #define bf_F(x) (((S0(x) + S1(x)) ^ S2(x)) + S3(x))
00047 #define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n])
00048
00049
00050 static struct box_t {
00051 u_int32_t *P;
00052 u_int32_t **S;
00053 char key[81];
00054 char keybytes;
00055 int lastuse;
00056 } box[BOXES];
00057
00058
00059
00060 static u_int32_t *bf_P;
00061 static u_int32_t **bf_S;
00062
00063 static void blowfish_encipher(u_int32_t * xl, u_int32_t * xr)
00064 {
00065 union aword Xl;
00066 union aword Xr;
00067
00068 Xl.word = *xl;
00069 Xr.word = *xr;
00070
00071 Xl.word ^= bf_P[0];
00072 ROUND(Xr, Xl, 1);
00073 ROUND(Xl, Xr, 2);
00074 ROUND(Xr, Xl, 3);
00075 ROUND(Xl, Xr, 4);
00076 ROUND(Xr, Xl, 5);
00077 ROUND(Xl, Xr, 6);
00078 ROUND(Xr, Xl, 7);
00079 ROUND(Xl, Xr, 8);
00080 ROUND(Xr, Xl, 9);
00081 ROUND(Xl, Xr, 10);
00082 ROUND(Xr, Xl, 11);
00083 ROUND(Xl, Xr, 12);
00084 ROUND(Xr, Xl, 13);
00085 ROUND(Xl, Xr, 14);
00086 ROUND(Xr, Xl, 15);
00087 ROUND(Xl, Xr, 16);
00088 Xr.word ^= bf_P[17];
00089
00090 *xr = Xl.word;
00091 *xl = Xr.word;
00092 }
00093
00094 static void blowfish_decipher(u_int32_t * xl, u_int32_t * xr)
00095 {
00096 union aword Xl;
00097 union aword Xr;
00098
00099 Xl.word = *xl;
00100 Xr.word = *xr;
00101
00102 Xl.word ^= bf_P[17];
00103 ROUND(Xr, Xl, 16);
00104 ROUND(Xl, Xr, 15);
00105 ROUND(Xr, Xl, 14);
00106 ROUND(Xl, Xr, 13);
00107 ROUND(Xr, Xl, 12);
00108 ROUND(Xl, Xr, 11);
00109 ROUND(Xr, Xl, 10);
00110 ROUND(Xl, Xr, 9);
00111 ROUND(Xr, Xl, 8);
00112 ROUND(Xl, Xr, 7);
00113 ROUND(Xr, Xl, 6);
00114 ROUND(Xl, Xr, 5);
00115 ROUND(Xr, Xl, 4);
00116 ROUND(Xl, Xr, 3);
00117 ROUND(Xr, Xl, 2);
00118 ROUND(Xl, Xr, 1);
00119 Xr.word ^= bf_P[0];
00120
00121 *xl = Xr.word;
00122 *xr = Xl.word;
00123 }
00124
00125
00126 static void blowfish_init(u_int8_t * key, int keybytes)
00127 {
00128 int i, j, bx;
00129 int lowest = 0;
00130 u_int32_t data;
00131 u_int32_t datal;
00132 u_int32_t datar;
00133 union aword temp;
00134
00135
00136
00137
00138 if (keybytes > 80)
00139 keybytes = 80;
00140
00141
00142 for (i = 0; i < BOXES; i++)
00143 if (box[i].P != NULL) {
00144 if ((box[i].keybytes == keybytes) &&
00145 (!strncmp((char *) (box[i].key), (char *) key, keybytes))) {
00146
00147 timer_get_now_sec(&box[i].lastuse);
00148 bf_P = box[i].P;
00149 bf_S = box[i].S;
00150 return;
00151 }
00152 }
00153
00154
00155 bx = (-1);
00156 for (i = 0; i < BOXES; i++) {
00157 if (box[i].P == NULL) {
00158 bx = i;
00159 i = BOXES + 1;
00160 }
00161 }
00162 if (bx < 0) {
00163
00164 timer_get_now_sec(&lowest);
00165 for (i = 0; i < BOXES; i++)
00166 if (box[i].lastuse <= lowest) {
00167 lowest = box[i].lastuse;
00168 bx = i;
00169 }
00170 free(box[bx].P);
00171 for (i = 0; i < 4; i++)
00172 free(box[bx].S[i]);
00173 free(box[bx].S);
00174 }
00175
00176
00177 box[bx].P = (u_int32_t *) malloc((bf_N + 2) * sizeof(u_int32_t));
00178 box[bx].S = (u_int32_t **) malloc(4 * sizeof(u_int32_t *));
00179 for (i = 0; i < 4; i++)
00180 box[bx].S[i] = (u_int32_t *) malloc(256 * sizeof(u_int32_t));
00181 bf_P = box[bx].P;
00182 bf_S = box[bx].S;
00183 box[bx].keybytes = keybytes;
00184 strlcpy(box[bx].key, key, keybytes + 1);
00185 timer_get_now_sec(&box[bx].lastuse);
00186
00187
00188
00189
00190 for (i = 0; i < bf_N + 2; i++)
00191 bf_P[i] = initbf_P[i];
00192 for (i = 0; i < 4; i++)
00193 for (j = 0; j < 256; j++)
00194 bf_S[i][j] = initbf_S[i][j];
00195
00196 j = 0;
00197 if (keybytes > 0) {
00198 for (i = 0; i < bf_N + 2; ++i) {
00199 temp.word = 0;
00200 temp.w.byte0 = key[j];
00201 temp.w.byte1 = key[(j + 1) % keybytes];
00202 temp.w.byte2 = key[(j + 2) % keybytes];
00203 temp.w.byte3 = key[(j + 3) % keybytes];
00204 data = temp.word;
00205 bf_P[i] = bf_P[i] ^ data;
00206 j = (j + 4) % keybytes;
00207 }
00208 }
00209 datal = 0x00000000;
00210 datar = 0x00000000;
00211 for (i = 0; i < bf_N + 2; i += 2) {
00212 blowfish_encipher(&datal, &datar);
00213 bf_P[i] = datal;
00214 bf_P[i + 1] = datar;
00215 }
00216 for (i = 0; i < 4; ++i) {
00217 for (j = 0; j < 256; j += 2) {
00218 blowfish_encipher(&datal, &datar);
00219 bf_S[i][j] = datal;
00220 bf_S[i][j + 1] = datar;
00221 }
00222 }
00223 }
00224
00225 #define SALT1 0xdeadd061
00226 #define SALT2 0x23f6b095
00227
00228
00229 static char *base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
00230
00231 static int base64dec(char c)
00232 {
00233 int i;
00234
00235 for (i = 0; i < 64; i++)
00236 if (base64[i] == c)
00237 return i;
00238 return 0;
00239 }
00240
00241 static void blowfish_encrypt_pass(char *text, char *new)
00242 {
00243 u_int32_t left, right;
00244 int n;
00245 char *p;
00246
00247 blowfish_init((unsigned char *) text, strlen(text));
00248 left = SALT1;
00249 right = SALT2;
00250 blowfish_encipher(&left, &right);
00251 p = new;
00252 *p++ = '+';
00253 n = 32;
00254 while (n > 0) {
00255 *p++ = base64[right & 0x3f];
00256 right = (right >> 6);
00257 n -= 6;
00258 }
00259 n = 32;
00260 while (n > 0) {
00261 *p++ = base64[left & 0x3f];
00262 left = (left >> 6);
00263 n -= 6;
00264 }
00265 *p = 0;
00266 }
00267
00268
00269
00270 static char *encrypt_string(char *key, char *str)
00271 {
00272 u_int32_t left, right;
00273 unsigned char *p;
00274 char *s, *dest, *d;
00275 int i;
00276
00277
00278 s = (char *) malloc(strlen(str) + 9);
00279 strcpy(s, str);
00280 if ((!key) || (!key[0]))
00281 return s;
00282 p = s;
00283 dest = (char *) malloc((strlen(str) + 9) * 2);
00284 while (*p)
00285 p++;
00286 for (i = 0; i < 8; i++)
00287 *p++ = 0;
00288 blowfish_init((unsigned char *) key, strlen(key));
00289 p = s;
00290 d = dest;
00291 while (*p) {
00292 left = ((*p++) << 24);
00293 left += ((*p++) << 16);
00294 left += ((*p++) << 8);
00295 left += (*p++);
00296 right = ((*p++) << 24);
00297 right += ((*p++) << 16);
00298 right += ((*p++) << 8);
00299 right += (*p++);
00300 blowfish_encipher(&left, &right);
00301 for (i = 0; i < 6; i++) {
00302 *d++ = base64[right & 0x3f];
00303 right = (right >> 6);
00304 }
00305 for (i = 0; i < 6; i++) {
00306 *d++ = base64[left & 0x3f];
00307 left = (left >> 6);
00308 }
00309 }
00310 *d = 0;
00311 free(s);
00312 return dest;
00313 }
00314
00315
00316
00317 static char *decrypt_string(char *key, char *str)
00318 {
00319 u_int32_t left, right;
00320 char *p, *s, *dest, *d;
00321 int i;
00322
00323
00324 s = (char *) malloc(strlen(str) + 12);
00325 strcpy(s, str);
00326 if ((!key) || (!key[0]))
00327 return s;
00328 p = s;
00329 dest = (char *) malloc(strlen(str) + 12);
00330 while (*p)
00331 p++;
00332 for (i = 0; i < 12; i++)
00333 *p++ = 0;
00334 blowfish_init((unsigned char *) key, strlen(key));
00335 p = s;
00336 d = dest;
00337 while (*p) {
00338 right = 0L;
00339 left = 0L;
00340 for (i = 0; i < 6; i++)
00341 right |= (base64dec(*p++)) << (i * 6);
00342 for (i = 0; i < 6; i++)
00343 left |= (base64dec(*p++)) << (i * 6);
00344 blowfish_decipher(&left, &right);
00345 for (i = 0; i < 4; i++)
00346 *d++ = (left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
00347 for (i = 0; i < 4; i++)
00348 *d++ = (right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
00349 }
00350 *d = 0;
00351 free(s);
00352 return dest;
00353 }
00354
00355 static char *script_encpass(char *pass)
00356 {
00357 char *buf;
00358
00359 buf = (char *)malloc(17);
00360 blowfish_encrypt_pass(pass, buf);
00361 return(buf);
00362 }
00363
00364 static script_command_t blowfish_script_cmds[] = {
00365 {"", "encpass", (Function) script_encpass, NULL, 1, "s", "string", SCRIPT_STRING | SCRIPT_FREE, 0},
00366 {"", "encrypt", (Function) encrypt_string, NULL, 2, "ss", "key string", SCRIPT_STRING | SCRIPT_FREE, 0},
00367 {"", "decrypt", (Function) decrypt_string, NULL, 2, "ss", "key string", SCRIPT_STRING | SCRIPT_FREE, 0},
00368 {0}
00369 };
00370
00371 static int blowfish_close(int why)
00372 {
00373 return(-1);
00374 }
00375
00376 EXPORT_SCOPE int start(egg_module_t *modinfo);
00377
00378 int start(egg_module_t *modinfo)
00379 {
00380 int i;
00381
00382 modinfo->name = "blowfish";
00383 modinfo->author = "eggdev";
00384 modinfo->version = "1.9.0";
00385 modinfo->description = "provides blowfish encryption/decryption";
00386 modinfo->close_func = blowfish_close;
00387
00388
00389 for (i = 0; i < BOXES; i++) {
00390 box[i].P = NULL;
00391 box[i].S = NULL;
00392 box[i].key[0] = 0;
00393 box[i].lastuse = 0L;
00394 }
00395 script_create_commands(blowfish_script_cmds);
00396 return(0);
00397 }
00398