#include "blowfish.h"
/* #define S(x,i) (bf_S[i][x.w.byte##i]) */
#define S0(x) (bf_S[0][x.w.byte0])
#define S1(x) (bf_S[1][x.w.byte1])
#define S2(x) (bf_S[2][x.w.byte2])
#define S3(x) (bf_S[3][x.w.byte3])
#define bf_F(x) (((S0(x) + S1(x)) ^ S2(x)) + S3(x))
#define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n])
static u_32bit_t bf_P[bf_N+2];
static u_32bit_t bf_S[4][256];
static void blowfish_encipher(u_32bit_t * xl, u_32bit_t * xr)
{
union aword Xl;
union aword Xr;
Xl.word = *xl;
Xr.word = *xr;
Xl.word ^= bf_P[0];
ROUND(Xr, Xl, 1);
ROUND(Xl, Xr, 2);
ROUND(Xr, Xl, 3);
ROUND(Xl, Xr, 4);
ROUND(Xr, Xl, 5);
ROUND(Xl, Xr, 6);
ROUND(Xr, Xl, 7);
ROUND(Xl, Xr, 8);
ROUND(Xr, Xl, 9);
ROUND(Xl, Xr, 10);
ROUND(Xr, Xl, 11);
ROUND(Xl, Xr, 12);
ROUND(Xr, Xl, 13);
ROUND(Xl, Xr, 14);
ROUND(Xr, Xl, 15);
ROUND(Xl, Xr, 16);
Xr.word ^= bf_P[17];
*xr = Xl.word;
*xl = Xr.word;
}
static void blowfish_decipher(u_32bit_t * xl, u_32bit_t * xr)
{
union aword Xl;
union aword Xr;
Xl.word = *xl;
Xr.word = *xr;
Xl.word ^= bf_P[17];
ROUND(Xr, Xl, 16);
ROUND(Xl, Xr, 15);
ROUND(Xr, Xl, 14);
ROUND(Xl, Xr, 13);
ROUND(Xr, Xl, 12);
ROUND(Xl, Xr, 11);
ROUND(Xr, Xl, 10);
ROUND(Xl, Xr, 9);
ROUND(Xr, Xl, 8);
ROUND(Xl, Xr, 7);
ROUND(Xr, Xl, 6);
ROUND(Xl, Xr, 5);
ROUND(Xr, Xl, 4);
ROUND(Xl, Xr, 3);
ROUND(Xr, Xl, 2);
ROUND(Xl, Xr, 1);
Xr.word ^= bf_P[0];
*xl = Xr.word;
*xr = Xl.word;
}
static void blowfish_init(u_8bit_t * key, int keybytes)
{
int i, j;
u_32bit_t datal, datar;
union aword temp;
if (keybytes > (bf_N + 2) * 4) keybytes = (bf_N + 2) * 4; // use max. 72 bytes (576 bit)
// Reset blowfish boxes to initial state
for (i = 0; i < bf_N + 2; i++) bf_P[i] = initbf_P[i];
for (i = 0; i < 4; i++)
for (j = 0; j < 256; j++)
bf_S[i][j] = initbf_S[i][j];
j = 0;
if (keybytes > 0) {
for (i = 0; i < bf_N + 2; ++i) {
temp.w.byte0 = key[j];
temp.w.byte1 = key[(j + 1) % keybytes];
temp.w.byte2 = key[(j + 2) % keybytes];
temp.w.byte3 = key[(j + 3) % keybytes];
bf_P[i] ^= temp.word;
temp.word = 0;
j = (j + 4) % keybytes;
}
}
datal = 0x00000000;
datar = 0x00000000;
for (i = 0; i < bf_N + 2; i += 2) {
blowfish_encipher(&datal, &datar);
bf_P[i] = datal;
bf_P[i + 1] = datar;
}
for (i = 0; i < 4; ++i) {
for (j = 0; j < 256; j += 2) {
blowfish_encipher(&datal, &datar);
bf_S[i][j] = datal;
bf_S[i][j + 1] = datar;
}
}
}
/* decode base64 string */
static int base64dec(char c)
{
int i;
for (i = 0; i < 64; i++)
if (B64[i] == c) return i;
return 0;
}
/* Returned string must be freed when done with it! */
int encrypt_string(char *key, char *str, char *dest, int len)
{
u_32bit_t left, right;
unsigned char *p;
char *s, *d;
int i;
if ((!key) || (!key[0])) return 0;
/* Pad fake string with 8 bytes to make sure there's enough */
s = (char *) malloc(len + 9);
strncpy(s, str, len);
memset(s+len, 0, 9);
blowfish_init((unsigned char *) key, strlen(key));
p = s;
d = dest;
while (*p) {
left = ((*p++) << 24);
left += ((*p++) << 16);
left += ((*p++) << 8);
left += (*p++);
right = ((*p++) << 24);
right += ((*p++) << 16);
right += ((*p++) << 8);
right += (*p++);
blowfish_encipher(&left, &right);
for (i = 0; i < 6; i++) {
*d++ = B64[right & 0x3f];
right = (right >> 6);
}
for (i = 0; i < 6; i++) {
*d++ = B64[left & 0x3f];
left = (left >> 6);
}
}
*d = 0;
free(s);
return 1;
}
int decrypt_string(char *key, char *str, char *dest, int len)
{
u_32bit_t left, right;
char *p, *s, *d;
int i;
/* Pad encoded string with 0 bits in case it's bogus */
if ((!key) || (!key[0])) return 0;
s = (char *) malloc(len + 12);
strncpy(s, str, len);
memset(s+len, 0, 12);
blowfish_init((unsigned char *) key, strlen(key));
p = s;
d = dest;
while (*p) {
right = 0L;
left = 0L;
for (i = 0; i < 6; i++) right |= (base64dec(*p++)) << (i * 6);
for (i = 0; i < 6; i++) left |= (base64dec(*p++)) << (i * 6);
blowfish_decipher(&left, &right);
for (i = 0; i < 4; i++) *d++ = (left & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
for (i = 0; i < 4; i++) *d++ = (right & (0xff << ((3 - i) * 8))) >> ((3 - i) * 8);
}
*d = 0;
free(s);
return 1;
}
int encrypt_key(char *key, char *encryptedKey)
{
int i;
strcpy(encryptedKey, "+OK ");
i=strlen(key);
encrypt_string(iniKey, key, encryptedKey+4, i>80 ? 80 : i);
}
syntax highlighted by Code2HTML, v. 0.9.1