i believe i have found a bug in BF_cbc_encrypt() in 0.9.5a.
        still not sure if it was repaired in 0.9.6beta2, i hope to test
        this with 0.9.6beta2 sooner (if you can, please).

        from cbc definition:

                        P1             P2             Pi
                         |              |              |
                  IV->->(X)    +>->->->(X)    +>->->->(X)
                         v     ^        v     ^        v
                      +-----+  ^     +-----+  ^     +-----+
                  k1->|  E  |  ^ k1->|  E  |  ^ k1->|  E  |
                      +-----+  ^     +-----+  ^     +-----+
                         v     ^        v     ^        v
                         +>->->+        +>->->+        +>->->
                         |              |              |
                         C1             C2             Ci

        if IV is all zero, C1 must be equal to ciphertext generated by
        simple single block cipher, like
                C1 == encrypt(P1, k1)
        but this is not the case for openssl BF_cbc_encrypt.

        the attached code emits the result like this:
>itojun[lychee:~] ./a.out 
>enc 0: 0
>enc 1: 0
>enc 2: 0
>dec 0: 0
>dec 1: 0
>dec 2: 0
>src(ossl cbc): 655f58083e07d1d2
>dst(ossl cbc): 2f939dbe9aeff6ca        <--- this has to be 4ac41f9e488b2a3f
>src(test cbc): 655f58083e07d1d2
>dst(test cbc): 4ac41f9e488b2a3f

        is my impression correct?  if so, i'll try to repair BF_cbc_encrypt.

itojun
#include <sys/types.h>
#include <stdio.h>
#include <openssl/blowfish.h>

u_int8_t enc[][8] = {
{ 0x65, 0x5f, 0x58, 0x08, 0x3e, 0x07, 0xd1, 0xd2,  },
{ 0x4a, 0xc4, 0x1f, 0x9e, 0x48, 0x8b, 0x2a, 0x3f,  },
{ 0x73, 0x02, 0x28, 0xa2, 0x48, 0x86, 0xbe, 0xfe,  },
{ 0xcc, 0x9c, 0x67, 0xad, 0x59, 0x1b, 0x99, 0x64,  },
{ 0xc8, 0x9f, 0x65, 0xac, 0x63, 0x1d, 0x9f, 0x61,  },
{ 0x9a, 0x34, 0x24, 0x0c, 0xeb, 0xf0, 0x25, 0x09,  },
};
u_int8_t dec[][8] = {
{ 0x4a, 0xc4, 0x1f, 0x9e, 0x48, 0x8b, 0x2a, 0x3f,  },
{ 0x65, 0x5f, 0x58, 0x08, 0x3e, 0x07, 0xd1, 0xd2,  },
{ 0xcc, 0x9c, 0x67, 0xad, 0x59, 0x1b, 0x99, 0x64,  },
{ 0x73, 0x02, 0x28, 0xa2, 0x48, 0x86, 0xbe, 0xfe,  },
{ 0x9a, 0x34, 0x24, 0x0c, 0xeb, 0xf0, 0x25, 0x09,  },
{ 0xc8, 0x9f, 0x65, 0xac, 0x63, 0x1d, 0x9f, 0x61,  },
};

int bf_cbc_encrypt __P((u_int8_t *, u_int8_t *, size_t, BF_KEY *, u_int8_t *));

int
dump8(title, p)
        char *title;
        u_int8_t *p;
{
        int i;

        printf("%s: ", title);
        for (i = 0; i < 8; i++)
                printf("%02x", p[i]);
        printf("\n");
}

int
main()
{
        BF_KEY k;
        int i;
        u_int8_t d[8];
        u_int8_t ivec[8];
        u_int8_t scbc[24];
        u_int8_t dcbc[24];

        BF_set_key(&k, 8, "hogehoge");
        for (i = 0; i < 3; i++) {
                memcpy(d, enc[i * 2], 8);
                BF_encrypt((BF_LONG *)d, &k);
                printf("enc %d: %d\n", i, memcmp(d, enc[i * 2 + 1], 8));
        }
        for (i = 0; i < 3; i++) {
                memcpy(d, dec[i * 2], 8);
                BF_decrypt((BF_LONG *)d, &k);
                printf("dec %d: %d\n", i, memcmp(d, dec[i * 2 + 1], 8));
        }

        memcpy(&scbc[0], enc[0], 8);
        memcpy(&scbc[8], enc[2], 8);
        memcpy(&scbc[16], enc[4], 8);

        memset(ivec, 0, sizeof(ivec));
        BF_cbc_encrypt(scbc, dcbc, 24, &k, ivec, BF_ENCRYPT);
        dump8("src(ossl cbc)", scbc);
        dump8("dst(ossl cbc)", dcbc);

        memset(ivec, 0, sizeof(ivec));
        bf_cbc_encrypt(scbc, dcbc, 24, &k, ivec);
        dump8("src(test cbc)", scbc);
        dump8("dst(test cbc)", dcbc);
}

/* home brew CBC code */
int
bf_cbc_encrypt(s, d, l, k, iv)
        u_int8_t *s;
        u_int8_t *d;
        size_t l;
        BF_KEY *k;
        u_int8_t *iv;
{
        size_t off;
        u_int8_t b[8];
        int i;
        u_int8_t *ivp;

        ivp = iv;
        for (off = 0; off < l; off += 8) {
                memcpy(d + off, s + off, 8);
                for (i = 0; i < 8; i++)
                        d[off + i] ^= ivp[i];
                BF_encrypt(&d[off], k);
                ivp = &d[off];
        }

        return 0;
}

Reply via email to