fix blowfish endianess confusion (thanks erik)

from /n/sources/patch/blowfish/readme:

Blowfish is broken. The order of the bytes in the ciphertext
is wrong. The problem is the conversion from the ciphertext
plaintext block to the array of u32int used by the core funcions
and vice versa.

This code has been tested on big endian and little endian
machines.

A test program is also included, bftets.c. It uses the
test vectors of blowfish available at
https://www.schneier.com/code/vectors.txt
This commit is contained in:
cinap_lenrek 2014-02-20 18:32:47 +01:00
parent eeac553c36
commit a6d5f9ccae
2 changed files with 325 additions and 100 deletions

View file

@ -0,0 +1,279 @@
#include <u.h>
#include <libc.h>
#include <libsec.h>
enum{
Bsz = 8,
};
typedef struct Testvector Testvector;
struct Testvector{
uchar key[Bsz];
uchar plain[Bsz];
uchar cipher[Bsz];
};
/*
* Blowfish test vectors from https://www.schneier.com/code/vectors.txt
*/
Testvector vector [] = {
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}},
{{0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}},
{{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}},
{{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}},
{{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}},
{{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}},
{{0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
{0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
{0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}},
{{0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
{0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
{0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}},
{{0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
{0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
{0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}},
{{0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
{0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
{0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}},
{{0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
{0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
{0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}},
{{0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
{0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
{0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}},
{{0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
{0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
{0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}},
{{0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
{0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
{0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}},
{{0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
{0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
{0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}},
{{0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
{0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
{0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}},
{{0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
{0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
{0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}},
{{0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
{0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
{0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}},
{{0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
{0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
{0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}},
{{0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
{0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
{0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}},
{{0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
{0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
{0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}},
{{0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
{0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
{0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}},
{{0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
{0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
{0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}},
{{0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
{0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
{0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}},
{{0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
{0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
{0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}},
{{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}},
{{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}},
{{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}},
{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}},
{{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}},
{{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}}
};
uchar CBCkey[16] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87
};
uchar CBCiv[8] = {
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
};
uchar CBCdata[29] = {
0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20,
0x66, 0x6F, 0x72, 0x20, 0x00
};
uchar CBCcipher[32] = {
0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6,
0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93,
0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9,
0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC
};
int
testECB(Testvector *t)
{
BFstate s;
int i;
uchar aux[Bsz];
memcpy(aux, t->plain, Bsz);
memset(&s, 0, sizeof(BFstate));
setupBFstate(&s, t->key, Bsz, nil);
bfECBencrypt(aux, Bsz, &s);
if(memcmp(aux, t->cipher, Bsz) != 0){
fprint(2, "ECB encrypt failed, ciphertext is:\n");
for(i = 0; i < Bsz; i++)
fprint(2, "%02X", aux[i]);
fprint(2, "\nand should be:\n");
for(i = 0; i < Bsz; i++)
fprint(2, "%02X", t->cipher[i]);
fprint(2, "\n");
return -1;
}
memset(&s, 0, sizeof(BFstate));
setupBFstate(&s, t->key, Bsz, nil);
bfECBdecrypt(aux, Bsz, &s);
if(memcmp(aux, t->plain, Bsz) != 0){
fprint(2, "ECB decrypt failed, plaintext is:\n");
for(i = 0; i < Bsz; i++)
fprint(2, "%02X", aux[i]);
fprint(2, "\nand should be:\n");
for(i = 0; i < Bsz; i++)
fprint(2, "%02X", t->plain[i]);
fprint(2, "\n");
return -1;
}
return 0;
}
int
testCBC(void)
{
BFstate s;
uchar aux[32];
int i;
memset(aux, 0 , sizeof(aux));
memcpy(aux, CBCdata, sizeof(CBCdata));
memset(&s, 0, sizeof(BFstate));
setupBFstate(&s, CBCkey, sizeof(CBCkey), CBCiv);
bfCBCencrypt(aux, 32, &s);
if(memcmp(aux, CBCcipher, sizeof(CBCcipher)) != 0){
fprint(2, "CBC encrypt failed, ciphertext is:\n");
for(i = 0; i < sizeof(aux); i++)
fprint(2, "%02X", aux[i]);
fprint(2, "\nand should be:\n");
for(i = 0; i < sizeof(CBCcipher); i++)
fprint(2, "%02X", CBCcipher[i]);
fprint(2, "\n");
return -1;
}
memset(&s, 0, sizeof(BFstate));
setupBFstate(&s, CBCkey, sizeof(CBCkey), CBCiv);
bfCBCdecrypt(aux, 32, &s);
if(memcmp(aux, CBCdata, sizeof(CBCdata)) != 0){
fprint(2, "CBC decrypt failed, plaintext is:\n");
for(i = 0; i < sizeof(aux); i++)
fprint(2, "%02X", aux[i]);
fprint(2, "\nand should be:\n");
for(i = 0; i < sizeof(CBCdata); i++)
fprint(2, "%02X", CBCdata[i]);
fprint(2, "\n");
return -1;
}
return 0;
}
void
main(int argc, char **argv)
{
int i;
if(argc != 1)
sysfatal("usage: %s", argv[0]);
for(i=0; i < nelem(vector); i++)
if(testECB(&vector[i]) < 0)
sysfatal("TestECB %d failed", i);
if(testCBC() < 0)
sysfatal("TestCBC failed");
exits(nil);
}

View file

@ -13,6 +13,37 @@ static u32int pbox[BFrounds+2];
static void bfencrypt(u32int *, BFstate *);
static void bfdecrypt(u32int *, BFstate *);
/*
* Endianess agnostic functions to convert a
* block (8-byte buffer) to a u32int array and
* viceversa.
*/
static void
buf2ints(uchar *p, u32int *b)
{
b[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
b[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
}
static void
ints2buf(u32int *b, uchar *p)
{
u32int u;
u = b[0];
p[0] = u>>24;
p[1] = u>>16;
p[2] = u>>8;
p[3] = u;
u = b[1];
p[4] = u>>24;
p[5] = u>>16;
p[6] = u>>8;
p[7] = u;
}
void
setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec)
{
@ -31,7 +62,7 @@ setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec)
memmove(s->ivec, ivec, sizeof(s->ivec));
else
memset(s->ivec, 0, sizeof(s->ivec));
memmove(s->pbox, pbox, sizeof(pbox));
memmove(s->sbox, sbox, sizeof(sbox));
@ -76,17 +107,13 @@ void
bfCBCencrypt(uchar *buf, int n, BFstate *s)
{
int i;
uchar *p;
u32int bo[2], bi[2], b;
u32int bo[2], bi[2];
assert((n & 7) == 0);
bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24);
bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24);
buf2ints(s->ivec, bo);
for(i=0; i < n; i += 8, buf += 8) {
bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
buf2ints(buf, bi);
bi[0] ^= bo[0];
bi[1] ^= bo[1];
@ -96,36 +123,9 @@ bfCBCencrypt(uchar *buf, int n, BFstate *s)
bo[0] = bi[0];
bo[1] = bi[1];
p = buf;
b = bo[0];
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b = bo[1];
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p = b;
ints2buf(bi, buf);
}
s->ivec[7] = bo[1] >> 24;
s->ivec[6] = bo[1] >> 16;
s->ivec[5] = bo[1] >> 8;
s->ivec[4] = bo[1];
s->ivec[3] = bo[0] >> 24;
s->ivec[2] = bo[0] >> 16;
s->ivec[1] = bo[0] >> 8;
s->ivec[0] = bo[0];
ints2buf(bo, s->ivec);
return;
}
@ -133,17 +133,13 @@ void
bfCBCdecrypt(uchar *buf, int n, BFstate *s)
{
int i;
uchar *p;
u32int b, bo[2], bi[2], xr[2];
u32int bo[2], bi[2], xr[2];
assert((n & 7) == 0);
bo[0] = s->ivec[0] | ((u32int) s->ivec[1]<<8) | ((u32int)s->ivec[2]<<16) | ((u32int)s->ivec[3]<<24);
bo[1] = s->ivec[4] | ((u32int) s->ivec[5]<<8) | ((u32int)s->ivec[6]<<16) | ((u32int)s->ivec[7]<<24);
buf2ints(s->ivec, bo);
for(i=0; i < n; i += 8, buf += 8) {
bi[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
bi[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
buf2ints(buf, bi);
xr[0] = bi[0];
xr[1] = bi[1];
@ -153,39 +149,12 @@ bfCBCdecrypt(uchar *buf, int n, BFstate *s)
bo[0] ^= bi[0];
bo[1] ^= bi[1];
p = buf;
b = bo[0];
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b = bo[1];
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p++ = b;
b >>= 8;
*p = b;
ints2buf(bo, buf);
bo[0] = xr[0];
bo[1] = xr[1];
}
s->ivec[7] = bo[1] >> 24;
s->ivec[6] = bo[1] >> 16;
s->ivec[5] = bo[1] >> 8;
s->ivec[4] = bo[1];
s->ivec[3] = bo[0] >> 24;
s->ivec[2] = bo[0] >> 16;
s->ivec[1] = bo[0] >> 8;
s->ivec[0] = bo[0];
ints2buf(bo, s->ivec);
return;
}
@ -196,20 +165,9 @@ bfECBencrypt(uchar *buf, int n, BFstate *s)
u32int b[2];
for(i=0; i < n; i += 8, buf += 8) {
b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
buf2ints(buf, b);
bfencrypt(b, s);
buf[7] = b[1] >> 24;
buf[6] = b[1] >> 16;
buf[5] = b[1] >> 8;
buf[4] = b[1];
buf[3] = b[0] >> 24;
buf[2] = b[0] >> 16;
buf[1] = b[0] >> 8;
buf[0] = b[0];
ints2buf(b, buf);
}
return;
@ -222,20 +180,9 @@ bfECBdecrypt(uchar *buf, int n, BFstate *s)
u32int b[2];
for(i=0; i < n; i += 8, buf += 8) {
b[0] = buf[0] | ((u32int) buf[1]<<8) | ((u32int)buf[2]<<16) | ((u32int)buf[3]<<24);
b[1] = buf[4] | ((u32int) buf[5]<<8) | ((u32int)buf[6]<<16) | ((u32int)buf[7]<<24);
buf2ints(buf, b);
bfdecrypt(b, s);
buf[7] = b[1] >> 24;
buf[6] = b[1] >> 16;
buf[5] = b[1] >> 8;
buf[4] = b[1];
buf[3] = b[0] >> 24;
buf[2] = b[0] >> 16;
buf[1] = b[0] >> 8;
buf[0] = b[0];
ints2buf(b, buf);
}
return;
@ -576,4 +523,3 @@ static u32int sbox[1024] = {
0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L,
};