[FFmpeg-devel] Patch for Cast128 algorithm implementation

Michael Niedermayer michaelni at gmx.at
Sun Oct 12 14:36:52 CEST 2014


On Sun, Oct 12, 2014 at 05:29:58PM +0530, supraja reddy wrote:
> Hello ,
> 
> I , Supraja , am interested to work with ffmpeg as a part of OPW internship
> . As a part of the qualification task , I have taken up the implementation
> of Cast 128 algorithm implementation . I have written the code for the same
> and have attached the patch of the same with this mail . It is currently
> written for ecb mode . It takes keysizes of 40 , 80 and 128 bits for now .
> 
> Please let me know if there are any further changes or suggestions .

please try tools/patcheck with your patch, it shows several issues
(some things it shows might be false positives though)

further comments below

[...]

> +static uint32_t func(uint32_t D, uint32_t Km, uint32_t Kr, int rnum)
> +{
> +    uint32_t I,t,val;
> +    switch(rnum%3){
> +        case 0:
> +            t=(Km-D);
> +            I=(t<<Kr)|(t>>(32-Kr));    
> +            val=((S1[IA(I)]+S2[IB(I)])^S3[IC(I)])-S4[ID(I)];
> +            break;
> +        case 1:  
> +            t=Km+D;
> +            I=(t<<Kr)|(t>>(32-Kr));    
> +            val=((S1[IA(I)]^S2[IB(I)])-S3[IC(I)])+S4[ID(I)];
> +            break;
> +        case 2:
> +            t=(Km^D);
> +            I=(t<<Kr)|(t>>(32-Kr));    
> +            val=((S1[IA(I)]-S2[IB(I)])+S3[IC(I)])^S4[ID(I)];
> +            break;
> +    }
> +    return val;
> +}
> +

> +static void GenerateRoundKeys(int rnds,uint32_t* K, uint32_t* q, uint32_t* p)

functions in ffmpeg generally are written in generate_round_keys() style


> +{
> +    p[0]=q[0]^S5[IB(q[3])]^S6[ID(q[3])]^S7[IA(q[3])]^S8[IC(q[3])]^S7[IA(q[2])];
> +    p[1]=q[2]^S5[IA(p[0])]^S6[IC(p[0])]^S7[IB(p[0])]^S8[ID(p[0])]^S8[IC(q[2])];
> +    p[2]=q[3]^S5[ID(p[1])]^S6[IC(p[1])]^S7[IB(p[1])]^S8[IA(p[1])]^S5[IB(q[2])];
> +    p[3]=q[1]^S5[IC(p[2])]^S6[IB(p[2])]^S7[ID(p[2])]^S8[IA(p[2])]^S6[ID(q[2])];
> +
> +    K[1]=S5[IA(p[2])]^S6[IB(p[2])]^S7[ID(p[1])]^S8[IC(p[1])]^S5[IC(p[0])];
> +    K[2]=S5[IC(p[2])]^S6[ID(p[2])]^S7[IB(p[1])]^S8[IA(p[1])]^S6[IC(p[1])];
> +    K[3]=S5[IA(p[3])]^S6[IB(p[3])]^S7[ID(p[0])]^S8[IC(p[0])]^S7[IB(p[2])];
> +    K[4]=S5[IC(p[3])]^S6[ID(p[3])]^S7[IB(p[0])]^S8[IA(p[0])]^S8[IA(p[3])];
> +
> +    q[0]=p[2]^S5[IB(p[1])]^S6[ID(p[1])]^S7[IA(p[1])]^S8[IC(p[1])]^S7[IA(p[0])];
> +    q[1]=p[0]^S5[IA(q[0])]^S6[IC(q[0])]^S7[IB(q[0])]^S8[ID(q[0])]^S8[IC(p[0])];
> +    q[2]=p[1]^S5[ID(q[1])]^S6[IC(q[1])]^S7[IB(q[1])]^S8[IA(q[1])]^S5[IB(p[0])];
> +    q[3]=p[3]^S5[IC(q[2])]^S6[IB(q[2])]^S7[ID(q[2])]^S8[IA(q[2])]^S6[ID(p[0])];
> +
> +    K[5]=S5[ID(q[0])]^S6[IC(q[0])]^S7[IA(q[3])]^S8[IB(q[3])]^S5[IA(q[2])];
> +    K[6]=S5[IB(q[0])]^S6[IA(q[0])]^S7[IC(q[3])]^S8[ID(q[3])]^S6[IB(q[3])];
> +    K[7]=S5[ID(q[1])]^S6[IC(q[1])]^S7[IA(q[2])]^S8[IB(q[2])]^S7[ID(q[0])];
> +    K[8]=S5[IB(q[1])]^S6[IA(q[1])]^S7[IC(q[2])]^S8[ID(q[2])]^S8[ID(q[1])];
> +
> +    p[0]=q[0]^S5[IB(q[3])]^S6[ID(q[3])]^S7[IA(q[3])]^S8[IC(q[3])]^S7[IA(q[2])];
> +    p[1]=q[2]^S5[IA(p[0])]^S6[IC(p[0])]^S7[IB(p[0])]^S8[ID(p[0])]^S8[IC(q[2])];
> +    p[2]=q[3]^S5[ID(p[1])]^S6[IC(p[1])]^S7[IB(p[1])]^S8[IA(p[1])]^S5[IB(q[2])];
> +    p[3]=q[1]^S5[IC(p[2])]^S6[IB(p[2])]^S7[ID(p[2])]^S8[IA(p[2])]^S6[ID(q[2])];
> +
> +    K[9]=S5[ID(p[0])]^S6[IC(p[0])]^S7[IA(p[3])]^S8[IB(p[3])]^S5[IB(p[2])];
> +    K[10]=S5[IB(p[0])]^S6[IA(p[0])]^S7[IC(p[3])]^S8[ID(p[3])]^S6[IA(p[3])];
> +    K[11]=S5[ID(p[1])]^S6[IC(p[1])]^S7[IA(p[2])]^S8[IB(p[2])]^S7[IC(p[0])];
> +    K[12]=S5[IB(p[1])]^S6[IA(p[1])]^S7[IC(p[2])]^S8[ID(p[2])]^S8[IC(p[1])];
> +
> +    q[0]=p[2]^S5[IB(p[1])]^S6[ID(p[1])]^S7[IA(p[1])]^S8[IC(p[1])]^S7[IA(p[0])];
> +    q[1]=p[0]^S5[IA(q[0])]^S6[IC(q[0])]^S7[IB(q[0])]^S8[ID(q[0])]^S8[IC(p[0])];
> +    q[2]=p[1]^S5[ID(q[1])]^S6[IC(q[1])]^S7[IB(q[1])]^S8[IA(q[1])]^S5[IB(p[0])];
> +    q[3]=p[3]^S5[IC(q[2])]^S6[IB(q[2])]^S7[ID(q[2])]^S8[IA(q[2])]^S6[ID(p[0])];
> +
> +    if(rnds==16) {
> +        K[13]=S5[IA(q[2])]^S6[IB(q[2])]^S7[ID(q[1])]^S8[IC(q[1])]^S5[ID(q[0])];
> +        K[14]=S5[IC(q[2])]^S6[ID(q[2])]^S7[IB(q[1])]^S8[IA(q[1])]^S6[ID(q[1])];
> +        K[15]=S5[IA(q[3])]^S6[IB(q[3])]^S7[ID(q[0])]^S8[IC(q[0])]^S7[IA(q[2])];
> +        K[16]=S5[IC(q[3])]^S6[ID(q[3])]^S7[IB(q[0])]^S8[IA(q[0])]^S8[IB(q[3])];
> +    }
> +}
> +
> +int av_cast5_init(AVCAST5* cs, const uint8_t *key, int key_bits)
> +{
> +    uint8_t newKey[16];
> +    int i;
> +    uint32_t p[4],q[4];
> +    if(key_bits%8!=0||key_bits<40||key_bits>128)
> +        return -1;

> +    memcpy(newKey,key,16*sizeof(key[0]));

this seems to read 128bit from the key argument, even when key_bits
is smaller, this might be unexpected to the user of this function
and might lead to a crash if the passed array is smaller


> +    if (key_bits!=128) {
> +        for(i=15;i>=key_bits/8;i--)
> +            newKey[i]=0x00;
> +    }
> +    if(key_bits==128){
> +        cs->rounds=16;
> +    } else {
> +        cs->rounds=12;
> +    }
> +    for(i=0;i<4;i++)
> +        q[i]=AV_RB32(newKey+(4*i));
> +    GenerateRoundKeys(cs->rounds,cs->Km,q,p);
> +    GenerateRoundKeys(cs->rounds,cs->Kr,q,p);
> +    for(i=0;i<cs->rounds;i++)
> +        cs->Kr[i]=cs->Kr[i]&0x1f;
> +    return 0;
> +}
> +
> +static void encipher(AVCAST5* cs,uint8_t* dst,const uint8_t* src)
> +{
> +    int i;
> +    uint32_t temp,sdst[2];
> +    sdst[0]=AV_RB32(src);
> +    sdst[1]=AV_RB32(src+4);
> +    for(i=1;i<=cs->rounds;i++){
> +        temp=sdst[1];
> +        sdst[1]=sdst[0]^(func(sdst[1],cs->Km[i],cs->Kr[i],i));
> +        sdst[0]=temp;
> +    }
> +    AV_WB32(dst,sdst[1]);
> +    AV_WB32(dst+4,sdst[0]);
> +}
> +
> +static void decipher(AVCAST5* cs,uint8_t* dst,const uint8_t* src)
> +{
> +    int i;
> +    uint32_t temp,sdst[2];
> +    sdst[0]=AV_RB32(src);
> +    sdst[1]=AV_RB32(src+4);

> +    for(i=cs->rounds;i>0;i--){
> +        temp=sdst[1];
> +        sdst[1]=sdst[0]^(func(sdst[1],cs->Km[i],cs->Kr[i],i));
> +        sdst[0]=temp;
> +    }

this and the previous loops should probably be unrolled by 3 to
avoid the switch and especially %3


> +    AV_WB32(dst,sdst[1]);
> +    AV_WB32(dst+4,sdst[0]);
> +}
> +
> +void av_cast5_crypt(AVCAST5* cs, uint8_t* dst, const uint8_t* src, int count, int decrypt)
> +{
> +    while(count--)
> +    {
> +        if(decrypt){
> +            decipher(cs,dst,src);            
> +        } else {
> +            encipher(cs,dst,src);
> +        }
> +        src=src+8;
> +        dst=dst+8;
> +    }
> +}
> +
> +#include<stdio.h>
> +#include<stdlib.h>
> +#include"log.h"
> +#include"lfg.h"
> +
> +#ifdef TEST
> +int main(int argc, char** argv)
> +{
> +    AVCAST5 cs;

> +    uint8_t Key[3][16]={{0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9a},
> +        {0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,0x23,0x45},
> +        {0x01,0x23,0x45,0x67,0x12}};
> +    uint8_t rpt[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};

static const uint8_t


> +    uint8_t rct[3][8]={{0x23,0x8b,0x4f,0xe5,0x84,0x7e,0x44,0xb2},
> +        {0xeb,0x6a,0x71,0x1a,0x2c,0x02,0x27,0x1b},
> +        {0x7a,0xc8,0x16,0xd1,0x6e,0x9b,0x30,0x2e}};
> +    int i,err=0;
> +    uint8_t temp[8];
> +    av_log_set_level(AV_LOG_DEBUG);
> +    av_cast5_init(&cs,Key[0],128);
> +    av_cast5_crypt(&cs,temp,rpt,1,0);
> +    for(i=0;i<8;i++){
> +        if(rct[0][i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rct[0][i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    av_cast5_crypt(&cs,temp,rct[0],1,1);
> +    for(i=0;i<8;i++){
> +        if(rpt[i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rpt[i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    av_cast5_init(&cs,Key[1],80);
> +    av_cast5_crypt(&cs,temp,rpt,1,0);
> +    for(i=0;i<8;i++){
> +        if(rct[1][i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rct[1][i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    av_cast5_crypt(&cs,temp,rct[1],1,1);
> +    for(i=0;i<8;i++){
> +        if(rpt[i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rpt[i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    av_cast5_init(&cs,Key[2],40);
> +    av_cast5_crypt(&cs,temp,rpt,1,0);
> +    for(i=0;i<8;i++){
> +        if(rct[2][i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rct[2][i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    av_cast5_crypt(&cs,temp,rct[2],1,1);
> +    for(i=0;i<8;i++){
> +        if(rpt[i]!=temp[i]){
> +            av_log(NULL,AV_LOG_ERROR,"%d %02x %02x\n",i,rpt[i],temp[i]);
> +            err=1;
> +        }
> +    }
> +    return err;
> +}
> +
> +#endif
> +
> +
> +
> +
> +
> +
> diff --git a/libavutil/cast5.h b/libavutil/cast5.h
> new file mode 100644
> index 0000000..d2196b9
> --- /dev/null
> +++ b/libavutil/cast5.h
> @@ -0,0 +1,37 @@
> +/*
> + * An implementation of the CAST128 algorithm
> + * Copyright (c) 2014 Supraja Meedinti
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg 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.
> + *
> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef AVUTIL_CAST5_H
> +#define AVUTIL_CAST5_H
> +
> +#include <stdint.h>
> +
> +#include "attributes.h"
> +#include "version.h"
> +
> +struct AVCAST5;
> +

> +int av_cast5_init(struct AVCAST5 *a, const uint8_t *key, int key_bits);
> +
> +void av_cast5_crypt(struct AVCAST5 *a, uint8_t *dst, const uint8_t *src, int count,int decrypt);

public functions should be documented (doxygen style)

thanks

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

What does censorship reveal? It reveals fear. -- Julian Assange
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20141012/1fe6c1db/attachment.asc>


More information about the ffmpeg-devel mailing list