[FFmpeg-devel] [PATCH] support encrypted asf

Michael Niedermayer michaelni
Tue Oct 9 21:36:07 CEST 2007


Hi

On Tue, Oct 09, 2007 at 07:53:04PM +0200, Reimar D?ffinger wrote:
> Hello,
> except for the missing license headers attached is the "final" (pending
> comments/objections) version.
> Please comment.
[...]
> +/**
> + * \brief find multiplicative inverse modulo 2 ^ 32
> + * \param v number to invert, must be odd!
> + * \return number so that result * v = 1 (mod 2^32)
> + */
> +static uint32_t inverse(uint32_t v) {
> +    // this initialization reduces the number of iterations
> +    // to 3 compared to 4 for = 2 - v and 5 for = 1
> +    uint32_t inverse = v * v * v;
> +    // uses a fixpoint-iteration to find the inverse very quickly
> +    int i = 3;
> +    do {
> +        inverse *= 2 - v * inverse;
> +    } while (--i);

is the resulting code (ever) smaller than if its unrolled?


> +    return inverse;
> +}
> +
> +/**
> + * \brief read keys from keybuf into keys
> + * \param keybuf buffer of 48 bytes containing the keys
> + * \param keys output key array of size 12 ints containing the keys
> + *             in native endianness for encryption
> + */
> +static void multiswap_init(const uint8_t *keybuf, uint32_t *keys) {

nitpick:
static void multiswap_init(const uint8_t keybuf[48], uint32_t keys[12]) {

[...]
> +static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
> +    int i;
> +    uint64_t res = 0;
> +    for (i = 0; i < shuffle_len; i++)
> +        res = (res << 1) | ((in >> *shuffle++) & 1);
> +    return res;
> +}
> +
> +static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
> +    int i;
> +    uint64_t res = 0;
> +    shuffle += shuffle_len - 1;
> +    for (i = 0; i < shuffle_len; i++) {
> +        res |= (in & 1) << *shuffle--;
> +        in >>= 1;
> +    }
> +    return res;
> +}
> +
> +static uint32_t f_func(uint32_t r, uint64_t k) {
> +    int i;
> +    uint32_t out = 0;
> +    // expand 32 bit data to 8 * 6 bit blocks
> +    uint64_t tmp = shuffle(r, E_shuffle, sizeof(E_shuffle));
> +    tmp ^= k;
> +    // apply S-boxes, those compress the data again from 8 * 6 to 8 * 4 bits
> +    for (i = 0; i < 8; i++) {
> +        uint32_t v = S_boxes[i][(tmp >> 43) & 0x1f];
> +        if (tmp & ((uint64_t)1 << 42)) v >>= 4;
> +        else v &= 0x0f;
> +        tmp <<= 6;
> +        out = (out << 4) | v;
> +    }
> +    out = shuffle(out, P_shuffle, sizeof(P_shuffle));
> +    return out;
> +}
> +
> +/**
> + * \brief rotate the two halves of the expanded 56 bit key each 1 bit left
> + *
> + * Note: the specification calls this "shift", so I kept it although
> + * it is confusing.
> + */
> +static uint64_t key_shift_left(uint64_t CDn) {
> +    uint64_t carries = (CDn >> 27) & 0x10000001;
> +    CDn <<= 1;
> +    CDn &= ~0x10000001;
> +    CDn |= carries;
> +    return CDn;
> +}
> +
> +/**
> + * \brief rotate the two halves of the expanded 56 bit key each 1 bit right
> + *
> + * Note: the specification calls this "shift", so I kept it although
> + * it is confusing.
> + */
> +static uint64_t key_shift_right(uint64_t CDn) {
> +    uint64_t carries = (CDn & 0x10000001) << 27;
> +    CDn >>= 1;
> +    CDn &= ~(0x10000001ULL << 27);
> +    CDn |= carries;
> +    return CDn;
> +}
> +
> +uint64_t ff_des_encdec(uint64_t in, uint64_t key, int decrypt) {
> +    int i;
> +    // discard parity bits from key and shuffle it into C and D parts
> +    uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
> +    // shuffle irrelevant to security but to ease hardware implementations
> +    in = shuffle(in, IP_shuffle, sizeof(IP_shuffle));
> +    for (i = 0; i < 16; i++) {
> +        uint64_t Kn;
> +        uint32_t f_res;
> +        if (!decrypt) {
> +            CDn = key_shift_left(CDn);
> +            if (i > 1 && i != 8 && i != 15)
> +                CDn = key_shift_left(CDn);
> +        }
> +        Kn = shuffle(CDn, PC2_shuffle, sizeof(PC2_shuffle));
> +        f_res = f_func(in, Kn);
> +        in = (in << 32) | (in >> 32);
> +        in ^= f_res;
> +        if (decrypt) {
> +            CDn = key_shift_right(CDn);
> +            if (i != 0 && i != 7 && i < 14)
> +                CDn = key_shift_right(CDn);
> +        }
> +    }
> +    in = (in << 32) | (in >> 32);
> +    // reverse shuffle used to ease hardware implementations
> +    in = shuffle_inv(in, IP_shuffle, sizeof(IP_shuffle));
> +    return in;
> +}

hmm, this doesnt look remotely optimal, maybe you should look at 
john the ripper IIRC it contains quite fast DES code. though surely far too
messy for us to use directly but i guess the ideas used in it could be
applied to our code as well


[...]
> +int main(void) {
> +    struct timeval tv;
> +    uint64_t key;
> +    uint64_t data;
> +    uint64_t ct;
> +    gettimeofday(&tv, NULL);
> +    srand(tv.tv_sec * 1000 * 1000 + tv.tv_usec);
> +    key = rand64();
> +    data = rand64();
> +    ct = des_encdec(data, key, 0);
> +    if (des_encdec(ct, key, 1) != data) {

ff_des_encdec ...


[...]
> Index: libavformat/rc4.c
> ===================================================================
> --- libavformat/rc4.c	(revision 0)
> +++ libavformat/rc4.c	(revision 0)
> @@ -0,0 +1,27 @@
> +// loosely based on LibTomCrypt by Tom St Denis
> +#include "common.h"
> +#include "rc4.h"
> +
> +void ff_rc4_enc(const uint8_t *key, int keylen, uint8_t *data, int datalen) {
> +    int i, j;
> +    uint8_t x, y;
> +    uint8_t state[256];
> +    for (i = 0; i < 256; i++)
> +        state[i] = i;
> +    y = 0;
> +    // j is i % keylen
> +    for (j = 0, i = 0; i < 256; i++, j++) {
> +        if (j == keylen) j = 0;
> +        y += state[i] + key[j];
> +        FFSWAP(uint8_t, state[i], state[y]);
> +    }
> +    // state initialized, now do the real encryption
> +    x = 1; y = state[1];
> +    while (datalen-- > 0) {
> +        uint8_t sum = state[x] + state[y];
> +        FFSWAP(uint8_t, state[x], state[y]);
> +        *data++ ^= state[sum];
> +        x++;
> +        y += state[x];
> +    }
> +}
> Index: libavformat/rc4.h
> ===================================================================
> --- libavformat/rc4.h	(revision 0)
> +++ libavformat/rc4.h	(revision 0)
> @@ -0,0 +1 @@
> +void ff_rc4_enc(const uint8_t *key, int keylen, uint8_t *data, int datalen);

feel free to commit rc4* to libavutil or libavformat anytime
and i dont think the use of uint8_t as index of arrays is very fast
have you benchmarked that against normal int &0xFF ?

also des/rc4/asfcrypt belong to seperate commits/patches



> Index: libavformat/Makefile
> ===================================================================
> --- libavformat/Makefile	(revision 10695)
> +++ libavformat/Makefile	(working copy)
> @@ -21,7 +21,7 @@
>  OBJS-$(CONFIG_AMR_MUXER)                 += amr.o
>  OBJS-$(CONFIG_APC_DEMUXER)               += apc.o
>  OBJS-$(CONFIG_APE_DEMUXER)               += ape.o
> -OBJS-$(CONFIG_ASF_DEMUXER)               += asf.o riff.o
> +OBJS-$(CONFIG_ASF_DEMUXER)               += asf.o riff.o asfcrypt.o des.o rc4.o

ohh no, lets pray diego doesnt notice this (asf,riff,as*,d*,r*)

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

No snowflake in an avalanche ever feels responsible. -- Voltaire
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20071009/06ad274a/attachment.pgp>



More information about the ffmpeg-devel mailing list