Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/blowfish/blowfish.c
1072 views
1
/*
2
blowfish.c -- handles:
3
encryption and decryption of passwords
4
5
The first half of this is very lightly edited from public domain
6
sourcecode. For simplicity, this entire module will remain public
7
domain.
8
*/
9
10
#include "blowfish.h"
11
#include "bf_tab.h" /* P-box P-array, S-box */
12
13
#define BOXES 3
14
15
/* #define S(x,i) (bf_S[i][x.w.byte##i]) */
16
#define S0(x) (bf_S[0][x.w.byte0])
17
#define S1(x) (bf_S[1][x.w.byte1])
18
#define S2(x) (bf_S[2][x.w.byte2])
19
#define S3(x) (bf_S[3][x.w.byte3])
20
#define bf_F(x) (((S0(x) + S1(x)) ^ S2(x)) + S3(x))
21
#define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n])
22
23
/* keep a set of rotating P & S boxes */
24
static struct box_t {
25
UWORD_32bits *P;
26
UWORD_32bits **S;
27
char key[81];
28
char keybytes;
29
time_t lastuse;
30
} blowbox[BOXES];
31
32
/*
33
static UWORD_32bits bf_P[bf_N+2];
34
static UWORD_32bits bf_S[4][256];
35
*/
36
37
static UWORD_32bits *bf_P;
38
static UWORD_32bits **bf_S;
39
40
static char blowfish_version[] = "BitchX blowfish encryption module v1.0";
41
42
static void blowfish_encipher (UWORD_32bits * xl, UWORD_32bits * xr)
43
{
44
union aword Xl;
45
union aword Xr;
46
47
Xl.word = *xl;
48
Xr.word = *xr;
49
50
Xl.word ^= bf_P[0];
51
ROUND(Xr, Xl, 1);
52
ROUND(Xl, Xr, 2);
53
ROUND(Xr, Xl, 3);
54
ROUND(Xl, Xr, 4);
55
ROUND(Xr, Xl, 5);
56
ROUND(Xl, Xr, 6);
57
ROUND(Xr, Xl, 7);
58
ROUND(Xl, Xr, 8);
59
ROUND(Xr, Xl, 9);
60
ROUND(Xl, Xr, 10);
61
ROUND(Xr, Xl, 11);
62
ROUND(Xl, Xr, 12);
63
ROUND(Xr, Xl, 13);
64
ROUND(Xl, Xr, 14);
65
ROUND(Xr, Xl, 15);
66
ROUND(Xl, Xr, 16);
67
Xr.word ^= bf_P[17];
68
69
*xr = Xl.word;
70
*xl = Xr.word;
71
}
72
73
static void blowfish_decipher (UWORD_32bits * xl, UWORD_32bits * xr)
74
{
75
union aword Xl;
76
union aword Xr;
77
78
Xl.word = *xl;
79
Xr.word = *xr;
80
81
Xl.word ^= bf_P[17];
82
ROUND(Xr, Xl, 16);
83
ROUND(Xl, Xr, 15);
84
ROUND(Xr, Xl, 14);
85
ROUND(Xl, Xr, 13);
86
ROUND(Xr, Xl, 12);
87
ROUND(Xl, Xr, 11);
88
ROUND(Xr, Xl, 10);
89
ROUND(Xl, Xr, 9);
90
ROUND(Xr, Xl, 8);
91
ROUND(Xl, Xr, 7);
92
ROUND(Xr, Xl, 6);
93
ROUND(Xl, Xr, 5);
94
ROUND(Xr, Xl, 4);
95
ROUND(Xl, Xr, 3);
96
ROUND(Xr, Xl, 2);
97
ROUND(Xl, Xr, 1);
98
Xr.word ^= bf_P[0];
99
100
*xl = Xr.word;
101
*xr = Xl.word;
102
}
103
104
static void blowfish_init (UBYTE_08bits * key, short keybytes)
105
{
106
int i, j, bx;
107
time_t lowest;
108
UWORD_32bits data;
109
UWORD_32bits datal;
110
UWORD_32bits datar;
111
union aword temp;
112
113
/* is buffer already allocated for this? */
114
for (i = 0; i < BOXES; i++)
115
if (blowbox[i].P != NULL)
116
{
117
if ((blowbox[i].keybytes == keybytes) &&
118
(strncmp((char *) (blowbox[i].key), (char *) key, keybytes) == 0))
119
{
120
blowbox[i].lastuse = now;
121
bf_P = blowbox[i].P;
122
bf_S = blowbox[i].S;
123
return;
124
}
125
}
126
/* no pre-allocated buffer: make new one */
127
/* set 'bx' to empty buffer */
128
bx = (-1);
129
for (i = 0; i < BOXES; i++)
130
{
131
if (blowbox[i].P == NULL)
132
{
133
bx = i;
134
i = BOXES + 1;
135
}
136
}
137
if (bx < 0)
138
{
139
/* find oldest */
140
lowest = now;
141
for (i = 0; i < BOXES; i++)
142
if (blowbox[i].lastuse <= lowest)
143
{
144
lowest = blowbox[i].lastuse;
145
bx = i;
146
}
147
new_free(&blowbox[bx].P);
148
for (i = 0; i < 4; i++)
149
new_free(&blowbox[bx].S[i]);
150
new_free(&blowbox[bx].S);
151
}
152
/* initialize new buffer */
153
/* uh... this is over 4k */
154
blowbox[bx].P = (UWORD_32bits *) new_malloc((bf_N + 2) * sizeof(UWORD_32bits));
155
blowbox[bx].S = (UWORD_32bits **) new_malloc(4 * sizeof(UWORD_32bits *));
156
for (i = 0; i < 4; i++)
157
blowbox[bx].S[i] = (UWORD_32bits *) new_malloc(256 * sizeof(UWORD_32bits));
158
bf_P = blowbox[bx].P;
159
bf_S = blowbox[bx].S;
160
blowbox[bx].keybytes = keybytes;
161
strncpy(blowbox[bx].key, key, keybytes);
162
blowbox[bx].lastuse = now;
163
164
/* robey: reset blowfish boxes to initial state */
165
/* (i guess normally it just keeps scrambling them, but here it's */
166
/* important to get the same encrypted result each time) */
167
for (i = 0; i < bf_N + 2; i++)
168
bf_P[i] = initbf_P[i];
169
for (i = 0; i < 4; i++)
170
for (j = 0; j < 256; j++)
171
bf_S[i][j] = initbf_S[i][j];
172
173
j = 0;
174
for (i = 0; i < bf_N + 2; ++i)
175
{
176
temp.word = 0;
177
temp.w.byte0 = key[j];
178
temp.w.byte1 = key[(j + 1) % keybytes];
179
temp.w.byte2 = key[(j + 2) % keybytes];
180
temp.w.byte3 = key[(j + 3) % keybytes];
181
data = temp.word;
182
bf_P[i] = bf_P[i] ^ data;
183
j = (j + 4) % keybytes;
184
}
185
186
datal = 0x00000000;
187
datar = 0x00000000;
188
189
for (i = 0; i < bf_N + 2; i += 2)
190
{
191
blowfish_encipher(&datal, &datar);
192
bf_P[i] = datal;
193
bf_P[i + 1] = datar;
194
}
195
196
for (i = 0; i < 4; ++i)
197
{
198
for (j = 0; j < 256; j += 2)
199
{
200
blowfish_encipher(&datal, &datar);
201
bf_S[i][j] = datal;
202
bf_S[i][j + 1] = datar;
203
}
204
}
205
}
206
207
208
/* stuff below this line was written by robey for eggdrop use */
209
210
/* convert 64-bit encrypted password to text for userfile */
211
static char *base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
212
213
static int base64dec (char c)
214
{
215
int i;
216
for (i = 0; i < 64; i++)
217
if (base64[i] == c)
218
return i;
219
return 0;
220
}
221
222
/* returned string must be freed when done with it! */
223
static char *encrypt_string (char * key, char * str)
224
{
225
UWORD_32bits left, right;
226
char *p, *s, *dest, *d;
227
int i;
228
dest = (char *) new_malloc((strlen(str) + 9) * 2);
229
/* pad fake string with 8 bytes to make sure there's enough */
230
s = (char *) new_malloc(strlen(str) + 9);
231
strcpy(s, str);
232
p = s;
233
while (*p)
234
p++;
235
for (i = 0; i < 8; i++)
236
*p++ = 0;
237
blowfish_init(key, strlen(key));
238
p = s;
239
d = dest;
240
while (*p)
241
{
242
left = ((*p++) << 24);
243
left += ((*p++) << 16);
244
left += ((*p++) << 8);
245
left += (*p++);
246
right = ((*p++) << 24);
247
right += ((*p++) << 16);
248
right += ((*p++) << 8);
249
right += (*p++);
250
blowfish_encipher(&left, &right);
251
for (i = 0; i < 6; i++)
252
{
253
*d++ = base64[right & 0x3f];
254
right = (right >> 6);
255
}
256
for (i = 0; i < 6; i++)
257
{
258
*d++ = base64[left & 0x3f];
259
left = (left >> 6);
260
}
261
}
262
*d = 0;
263
new_free(&s);
264
return dest;
265
}
266
267
/* returned string must be freed when done with it! */
268
static char *decrypt_string (char * key, char * str)
269
{
270
UWORD_32bits left, right;
271
char *p, *s, *dest, *d;
272
int i;
273
dest = (char *) new_malloc(strlen(str) + 12);
274
/* pad encoded string with 0 bits in case it's bogus */
275
s = (char *) new_malloc(strlen(str) + 12);
276
strcpy(s, str);
277
p = s;
278
while (*p)
279
p++;
280
for (i = 0; i < 12; i++)
281
*p++ = 0;
282
blowfish_init(key, strlen(key));
283
p = s;
284
d = dest;
285
while (*p) {
286
right = 0L;
287
left = 0L;
288
for (i = 0; i < 6; i++)
289
right |= (base64dec(*p++)) << (i * 6);
290
for (i = 0; i < 6; i++)
291
left |= (base64dec(*p++)) << (i * 6);
292
blowfish_decipher(&left, &right);
293
for (i = 0; i < 4; i++)
294
*d++ = (left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
295
for (i = 0; i < 4; i++)
296
*d++ = (right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
297
}
298
*d = 0;
299
new_free(&s);
300
return dest;
301
}
302
303
#ifdef WANT_TCL
304
static int tcl_encrypt STDVAR
305
{
306
char *p;
307
BADARGS(3, 3, " key string");
308
p = encrypt_string(argv[1], argv[2]);
309
Tcl_AppendResult(irp, p, NULL);
310
new_free(&p);
311
return TCL_OK;
312
}
313
314
static int tcl_decrypt STDVAR
315
{
316
char *p;
317
BADARGS(3, 3, " key string");
318
p = decrypt_string(argv[1], argv[2]);
319
Tcl_AppendResult(irp, p, NULL);
320
new_free(&p);
321
return TCL_OK;
322
}
323
324
#endif /* WANT_TCL */
325
326
BUILT_IN_FUNCTION(ircii_encrypt)
327
{
328
char *p, *q, *r;
329
if (!input)
330
return m_strdup("1");
331
p = input;
332
if ((q = strchr(input, ' ')))
333
{
334
*q++ = 0;
335
r = encrypt_string(p, q);
336
return r;
337
}
338
return m_strdup(empty_string);
339
}
340
341
BUILT_IN_FUNCTION(ircii_decrypt)
342
{
343
char *p, *q, *r;
344
if (!input)
345
return m_strdup("1");
346
p = input;
347
if ((q = strchr(input, ' ')))
348
{
349
*q++ = 0;
350
r = decrypt_string(p, q);
351
return r;
352
}
353
return m_strdup(empty_string);
354
}
355
356
int Blowfish_Init(IrcCommandDll **intp, Function_ptr *global_table)
357
{
358
int i;
359
initialize_module("Blowfish");
360
361
for (i = 0; i < BOXES; i++) {
362
blowbox[i].P = NULL;
363
blowbox[i].S = NULL;
364
blowbox[i].key[0] = 0;
365
blowbox[i].lastuse = 0L;
366
}
367
#ifdef WANT_TCL
368
Tcl_CreateCommand(tcl_interp, "encrypt", tcl_encrypt, NULL, NULL);
369
Tcl_CreateCommand(tcl_interp, "decrypt", tcl_decrypt, NULL, NULL);
370
Tcl_SetVar(tcl_interp, "blowfish_version", blowfish_version, TCL_GLOBAL_ONLY);
371
#endif
372
add_module_proc(ALIAS_PROC, "blowfish", "encrypt", "Blowfish Encryption", 0, 0, ircii_encrypt, NULL);
373
add_module_proc(ALIAS_PROC, "blowfish", "decrypt", "Blowfish Decryption", 0, 0, ircii_decrypt, NULL);
374
put_it("%s loaded.", blowfish_version);
375
put_it("Adapted from eggdrop by By-Tor");
376
return 0;
377
}
378
379
int Blowfish_Cleanup(IrcCommandDll **intp)
380
{
381
#ifdef WANT_TCL
382
Tcl_DeleteCommand(tcl_interp, "encrypt");
383
Tcl_DeleteCommand(tcl_interp, "decrypt");
384
Tcl_UnsetVar(tcl_interp, "blowfish_version", TCL_GLOBAL_ONLY);
385
#endif
386
return 1;
387
}
388
389