On Sat, Jun 30, 2012 at 03:22:16PM +0200, Samuel Pitoiset wrote:
> ---
>  libavutil/Makefile |    1 +
>  libavutil/bf.c     |  410 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  libavutil/bf.h     |   59 ++++++++
>  3 files changed, 470 insertions(+), 0 deletions(-)
>  create mode 100644 libavutil/bf.c
>  create mode 100644 libavutil/bf.h

nit: more meaningful filename would be better (what's wrong with
blowfish.[ch]?)

> diff --git a/libavutil/Makefile b/libavutil/Makefile
> index 6fe174b..b1f7183 100644
> --- a/libavutil/Makefile
> +++ b/libavutil/Makefile
> @@ -51,6 +51,7 @@ OBJS = adler32.o                                            
>             \
>         audioconvert.o                                                   \
>         avstring.o                                                       \
>         base64.o                                                         \
> +       bf.o                                                             \
>         cpu.o                                                            \
>         crc.o                                                            \
>         des.o                                                            \
> diff --git a/libavutil/bf.c b/libavutil/bf.c
> new file mode 100644
> index 0000000..afaeeae
> --- /dev/null
> +++ b/libavutil/bf.c
> @@ -0,0 +1,410 @@
> +/*
> + * Blowfish algorithm
> + * Copyright (c) 2012 Samuel Pitoiset
> + *
> + * loosely based on Paul Kocher's implementation
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#include "avutil.h"
> +#include "common.h"
> +#include "bf.h"
> +
> +typedef struct AVBF AVBF;

I think it would be better to declare

typedef struct AVBlowfish {
 ...
} AVBlowfish;

in the header. And the name should be more meaningful.
Same for other 'av_bf_*' names.

> +static const uint32_t orig_p[BF_ROUNDS + 2] = {
> +    0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
> +    0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
> +    0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
> +    0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
> +    0x9216D5D9L, 0x8979FB1BL
> +};

'L' suffixes are not needed ('U' would be more appropriate here.

> +
> +static const uint32_t orig_s[4][256] = {
> +    {   0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,

nit: formatting like

static const uint32_t orig_s[4][256] = {
    {
        0xB8E1AFEDu, 0x6A267E96u, 0xBA7C9045u, 0xF12C7F99u,
        ...
    },
    {
        ...
    }
};

would look better (but Diego might suggest even better formatting)
[...]

> +static uint32_t F(AVBF *bf, uint32_t x)
> +{
> +    uint16_t a, b, c, d;
> +    uint32_t y;
> +
> +    d = (uint16_t)(x & 0xFF);
> +    x >>= 8;
> +    c = (uint16_t)(x & 0xFF);
> +    x >>= 8;
> +    b = (uint16_t)(x & 0xFF);
> +    x >>= 8;
> +    a = (uint16_t)(x & 0xFF);
> +    y = bf->s[0][a] + bf->s[1][b];
> +    y = y ^ bf->s[2][c];
> +    y = y + bf->s[3][d];

this can be simplified by eliminating temporary variables:

   y   = bf->s[0][(x >> 24) & 0xFF];
   y  += bf->s[1][(x >> 16) & 0xFF];
   y  ^= bf->s[2][(x >>  8) & 0xFF];
   y  += bf->s[3][ x        & 0xFF];

> +    return y;
> +}
> +
> +void av_bf_init(AVBF *bf, const uint8_t *key, int key_len)
> +{
> +    uint32_t data, datal, datar;
> +    int i, j, k;
> +
> +    for (i = 0; i < 4; i++) {
> +        for (j = 0; j < 256; j++)
> +            bf->s[i][j] = orig_s[i][j];
> +    }

memcpy(bf->s, orig_s, sizeof(orig_s)) ?

> +    j = 0;
> +    for (i = 0; i < BF_ROUNDS + 2; ++i) {
> +        data = 0x00000000;
> +        for (k = 0; k < 4; ++k) {

make it k++ for consistency

> +            data = (data << 8) | key[j];
> +            j = j + 1;

I'd suggest    data = (data << 8) | key[j++];

> +            if (j >= key_len)
> +                j = 0;
> +        }
> +        bf->p[i] = orig_p[i] ^ data;
> +    }
> +
> +    datal = 0x00000000;
> +    datar = 0x00000000;
> +
> +    for (i = 0; i < BF_ROUNDS + 2; i += 2) {
> +        av_bf_encrypt(bf, &datal, &datar);
> +        bf->p[i]     = datal;
> +        bf->p[i + 1] = datar;
> +    }
> +
> +    for (i = 0; i < 4; ++i) {
> +        for (j = 0; j < 256; j += 2) {
> +            av_bf_encrypt(bf, &datal, &datar);
> +            bf->s[i][j]     = datal;
> +            bf->s[i][j + 1] = datar;
> +        }
> +    }
> +}
> +
> +void av_bf_encrypt(AVBF *bf, uint32_t *xl, uint32_t *xr)
> +{
> +    uint32_t Xl, Xr, tmp;
> +    int i;
> +
> +    Xl = *xl;
> +    Xr = *xr;
> +
> +    for (i = 0; i < BF_ROUNDS; ++i) {
> +        Xl = Xl ^ bf->p[i];
> +        Xr = F(bf, Xl) ^ Xr;

make it uniform:
1)
   Xl = Xl ^ bf->p[i];
   Xr = Xr ^ F(bf, Xl);
or 2)
   Xl ^= bf->p[i];
   Xr ^= F(bf, Xl);

> +
> +        tmp = Xl;
> +        Xl  = Xr;
> +        Xr  = tmp;

FFSWAP(uint32_t, Xl, Xr);

> +    }
> +
> +    tmp = Xl;
> +    Xl  = Xr;
> +    Xr  = tmp;

here too

> +
> +    Xr = Xr ^ bf->p[BF_ROUNDS];
> +    Xl = Xl ^ bf->p[BF_ROUNDS + 1];
> +
> +    *xl = Xl;
> +    *xr = Xr;
> +}
> +
> +void av_bf_decrypt(AVBF *bf, uint32_t *xl, uint32_t *xr)
> +{
> +    uint32_t Xl, Xr, tmp;
> +    int i;
> +
> +    Xl = *xl;
> +    Xr = *xr;
> +
> +    for (i = BF_ROUNDS + 1; i > 1; --i) {
> +        Xl = Xl ^ bf->p[i];
> +        Xr = F(bf, Xl) ^ Xr;
> +
> +        tmp = Xl;
> +        Xl  = Xr;
> +        Xr  = tmp;
> +    }
> +
> +    tmp = Xl;
> +    Xl  = Xr;
> +    Xr  = tmp;
> +
> +    Xr = Xr ^ bf->p[1];
> +    Xl = Xl ^ bf->p[0];
> +
> +    *xl = Xl;
> +    *xr = Xr;
> +}

Looks like crypt() and decrypt() differ only by direction of rounds applied,
maybe you should factor out it and have simply:

static void blowfish_crypt(AVBlowfish *bf, uint32_t *xl, uint32_t *xr,
                           int direction)
{
...
}

void av_blowfish_decrypt(AVBlowfish *bf, uint32_t *xl, uint32_t *xr)
{
    blowfish_crypt(bf, xl, xr, 1);
}

> diff --git a/libavutil/bf.h b/libavutil/bf.h
> new file mode 100644
> index 0000000..a4cba13
> --- /dev/null
> +++ b/libavutil/bf.h
> @@ -0,0 +1,59 @@
> +/*
> + * Blowfish algorithm
> + *
> + * This file is part of Libav.
> + *
> + * Libav is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * Libav is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +#ifndef AVUTIL_BF_H
> +#define AVUTIL_BF_H
> +
> +#include <stdint.h>
> +
> +#define BF_ROUNDS 16
> +
> +struct AVBF {
> +    uint32_t p[BF_ROUNDS + 2];
> +    uint32_t s[4][256];
> +};
> +
> +/**
> + * @brief Initializes an AVBF context.
> + *
> + * @param key a key
> + * @param key_len length of the key

all parameters should be documented

> + */
> +void av_bf_init(struct AVBF *bf, const uint8_t *key, int key_len);
> +
> +/**
> + * @brief Encrypts using the Blowfish algorithm.
> + *
> + * @param bf an AVBF context
> + * @param xl TODO : what is the good description here?
> + * @param xr TODO 

Those are supposed to be eight bytes of input that should be encrypted.
And you're supposed to use it _knowingly_ ;)

Feel free to have a look at C++ implementation -
http://www.schneier.com/code/bfsh-con.zip
It has wrapper that shows how to use that on real input/output.

> + */
> +void av_bf_encrypt(struct AVBF *bf, uint32_t *xl, uint32_t *xr);
> +
> +/**
> + * @brief Decrypts using the Blowfish algorithm.
> + *
> + * @param bf an AVBF context
> + * @param xl TODO
> + * @param xr TODO
> + */
> +void av_bf_decrypt(struct AVBF *bf, uint32_t *xl, uint32_t *xr);
> +
> +#endif /* AVUTIL_BF_H */
> -- 

Also there's self-test program missing. Look at libavutil/sha.c for an example
of one, I'm sure Diego will help with Makefile part for it.
Test vectors are available at http://www.schneier.com/code/vectors2.txt
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to