security-scripts/dns/zodiac/src/cipher-blowfish.c

305 lines
6.2 KiB
C
Raw Normal View History

2013-06-04 14:33:16 +02:00
/* zodiac - advanced dns spoofer
*
* blowfish encryption routines, reference implementation
*
* by: (unknown, possible bruce schneier)
* additions by random
* slightly modified by scut
*/
#include <string.h>
#include "cipher-sha1.h"
#include "cipher-blowfish.h"
#include "cipher-blowfish-tab.h"
#include "common.h"
#define BOXES 3
/* #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])
struct box_t {
UWORD_32bits *P;
UWORD_32bits **S;
char key[81];
char keybytes;
} box[BOXES];
static void blowfish_encipher (UWORD_32bits *xl, UWORD_32bits *xr);
static void blowfish_decipher (UWORD_32bits *xl, UWORD_32bits *xr);
static void blowfish_init (UBYTE_08bits *key, short keybytes, int bxtouse);
UWORD_32bits *bf_P;
UWORD_32bits **bf_S;
static void
blowfish_encipher (UWORD_32bits *xl, UWORD_32bits *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 (UWORD_32bits *xl, UWORD_32bits *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 (UBYTE_08bits *key, short keybytes, int bxtouse)
{
int i, j, bx;
UWORD_32bits data;
UWORD_32bits datal;
UWORD_32bits datar;
union aword temp;
for (i = 0 ; i < BOXES ; i++)
if (box[i].P != NULL) {
if ((box[i].keybytes == keybytes) &&
(strncmp ((char *) (box[i].key), (char *) key, keybytes) == 0))
{
bf_P = box[i].P;
bf_S = box[i].S;
return;
}
}
bx = (-1);
for (i = 0 ; i < BOXES ; i++) {
if (box[i].P == NULL) {
bx = i;
i = BOXES + 1;
}
}
if (bx < 0) {
bx = bxtouse;
free (box[bx].P);
for (i = 0 ; i < 4 ; i++)
free (box[bx].S[i]);
free (box[bx].S);
}
box[bx].P = (UWORD_32bits *) malloc ((bf_N + 2) * sizeof (UWORD_32bits));
box[bx].S = (UWORD_32bits **) malloc (4 * sizeof (UWORD_32bits *));
for (i = 0 ; i < 4 ; i++)
box[bx].S[i] = (UWORD_32bits *) malloc (256 * sizeof (UWORD_32bits));
bf_P = box[bx].P;
bf_S = box[bx].S;
box[bx].keybytes = keybytes;
strncpy (box[bx].key, key, keybytes);
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];
for (i = 0, j = 0; i < bf_N + 2; ++i) {
temp.word = 0;
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];
data = temp.word;
bf_P[i] = bf_P[i] ^ data;
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;
}
}
}
unsigned char *
bf_encipher (char *keyphrase, unsigned char *data, size_t data_len, size_t *result_len)
{
UWORD_32bits left, right; /* blowfish halfs */
unsigned long int dp_i; /* data pointer relative */
unsigned char key[20]; /* hash used as bf key */
unsigned char *data_enc,
*dp;
unsigned char *sp,
*source;
long int do_count;
/* build a strong hash out of a weak keyphrase
*/
SHA1Hash (keyphrase, key);
blowfish_init (key, sizeof (key), 0);
sp = source = xcalloc (1, data_len + (8 - (data_len % 8)) + 1);
memcpy (source, data, data_len);
dp = data_enc = xcalloc (1, data_len + 9);
do_count = data_len / 8;
if ((data_len % 8) != 0)
do_count += 1;
*result_len = do_count * 8;
for (dp_i = 0 ; dp_i < do_count ; ++dp_i) {
left = ((*sp++) << 24);
left |= ((*sp++) << 16);
left |= ((*sp++) << 8);
left |= (*sp++);
right = ((*sp++) << 24);
right |= ((*sp++) << 16);
right |= ((*sp++) << 8);
right |= (*sp++);
blowfish_encipher (&left, &right);
*dp++ = (right & 0xff000000) >> 24;
*dp++ = (right & 0x00ff0000) >> 16;
*dp++ = (right & 0x0000ff00) >> 8;
*dp++ = (right & 0x000000ff);
*dp++ = (left & 0xff000000) >> 24;
*dp++ = (left & 0x00ff0000) >> 16;
*dp++ = (left & 0x0000ff00) >> 8;
*dp++ = (left & 0x000000ff);
}
free (source);
return (data_enc);
}
unsigned char *
bf_decipher (char *keyphrase, unsigned char *data, size_t data_len)
{
UWORD_32bits left, right; /* blowfish halfs */
unsigned long int dp_i; /* data pointer relative */
unsigned char key[20]; /* hash used as bf key */
unsigned char *data_dec,
*dp;
unsigned char *sp;
long int do_count;
/* sanity checking
*/
if ((data_len % 8) != 0)
return (NULL);
/* build a strong hash out of a weak keyphrase
*/
SHA1Hash (keyphrase, key);
blowfish_init (key, sizeof (key), 0);
sp = data;
dp = data_dec = xcalloc (1, data_len);
do_count = data_len / 8;
for (dp_i = 0 ; dp_i < do_count ; ++dp_i) {
right = ((*sp++) << 24);
right |= ((*sp++) << 16);
right |= ((*sp++) << 8);
right |= (*sp++);
left = ((*sp++) << 24);
left |= ((*sp++) << 16);
left |= ((*sp++) << 8);
left |= (*sp++);
blowfish_decipher (&left, &right);
*dp++ = (left & 0xff000000) >> 24;
*dp++ = (left & 0x00ff0000) >> 16;
*dp++ = (left & 0x0000ff00) >> 8;
*dp++ = (left & 0x000000ff);
*dp++ = (right & 0xff000000) >> 24;
*dp++ = (right & 0x00ff0000) >> 16;
*dp++ = (right & 0x0000ff00) >> 8;
*dp++ = (right & 0x000000ff);
}
return (data_dec);
}