aes.c 5.12 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1
/*
Michael Niedermayer's avatar
Michael Niedermayer committed
2
 * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at> and Reimar Dffinger
Michael Niedermayer's avatar
Michael Niedermayer committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * 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
 */

#include "common.h"
#include "log.h"
#include "aes.h"

typedef struct AVAES{
    uint8_t state[4][4];
    uint8_t round_key[15][4][4];
    int rounds;
}AVAES;

31 32
static const uint8_t rcon[11] = {
  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c
Michael Niedermayer's avatar
Michael Niedermayer committed
33 34 35 36
};

static uint8_t     sbox[256];
static uint8_t inv_sbox[256];
37 38 39 40 41 42 43
#ifdef CONFIG_SMALL
static uint32_t enc_multbl[1][256];
static uint32_t dec_multbl[1][256];
#else
static uint32_t enc_multbl[4][256];
static uint32_t dec_multbl[4][256];
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
44

45 46 47
static inline void addkey(uint64_t state[2], uint64_t round_key[2]){
    state[0] ^= round_key[0];
    state[1] ^= round_key[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
48 49 50 51 52 53 54
}

#define SUBSHIFT0(s, box)         s[0]=box[s[ 0]]; s[ 4]=box[s[ 4]];          s[ 8]=box[s[ 8]]; s[12]=box[s[12]];
#define SUBSHIFT1(s, box) t=s[0]; s[0]=box[s[ 4]]; s[ 4]=box[s[ 8]];          s[ 8]=box[s[12]]; s[12]=box[t];
#define SUBSHIFT2(s, box) t=s[0]; s[0]=box[s[ 8]]; s[ 8]=box[    t]; t=s[ 4]; s[ 4]=box[s[12]]; s[12]=box[t];
#define SUBSHIFT3(s, box) t=s[0]; s[0]=box[s[12]]; s[12]=box[s[ 8]];          s[ 8]=box[s[ 4]]; s[ 4]=box[t];

55
static inline int mul(int a, int b, uint8_t alog8[256]){
Michael Niedermayer's avatar
Michael Niedermayer committed
56 57 58 59
    if(a==255) return 0;
    else       return alog8[a+b];
}

60 61 62 63 64 65 66 67 68 69 70 71 72
#define ROT(x,s) ((x>>s)|(x<<(32-s))

static inline void mix(uint8_t state[4][4], uint32_t multbl[4][256]){
    int i;
    for(i=0; i<4; i++)
#ifdef CONFIG_SMALL
        ((uint32_t *)(state))[i] =     multbl[0][state[i][0]]     ^ ROT(multbl[0][state[i][1]], 8)
                                  ^ROT(multbl[0][state[i][2]],16) ^ ROT(multbl[0][state[i][3]],24);

#else
        ((uint32_t *)(state))[i] = multbl[0][state[i][0]] ^ multbl[1][state[i][1]]
                                  ^multbl[2][state[i][2]] ^ multbl[3][state[i][3]];
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
73 74 75 76 77 78 79 80 81
}

void av_aes_decrypt(AVAES *a){
    int t, r;

    for(r=a->rounds-1; r>=0; r--){
        if(r==a->rounds-1)
            addkey(a->state, a->round_key[r+1]);
        else
82
            mix(a->state, dec_multbl);
Michael Niedermayer's avatar
Michael Niedermayer committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
        SUBSHIFT0((a->state[0]+0), inv_sbox)
        SUBSHIFT3((a->state[0]+1), inv_sbox)
        SUBSHIFT2((a->state[0]+2), inv_sbox)
        SUBSHIFT1((a->state[0]+3), inv_sbox)
        addkey(a->state, a->round_key[r]);
    }
}

void av_aes_encrypt(AVAES *a){
    int r, t;

    for(r=0; r<a->rounds; r++){
        addkey(a->state, a->round_key[r]);
        SUBSHIFT0((a->state[0]+0), sbox)
        SUBSHIFT1((a->state[0]+1), sbox)
        SUBSHIFT2((a->state[0]+2), sbox)
        SUBSHIFT3((a->state[0]+3), sbox)
        if(r==a->rounds-1)
            addkey(a->state, a->round_key[r+1]);
        else
103
            mix(a->state, enc_multbl); //FIXME replace log8 by const / optimze mix as this can be simplified alot
Michael Niedermayer's avatar
Michael Niedermayer committed
104 105 106 107
    }
}

// this is based on the reference AES code by Paulo Barreto and Vincent Rijmen
Michael Niedermayer's avatar
Michael Niedermayer committed
108
AVAES *av_aes_init(uint8_t *key, int key_bits) {
Michael Niedermayer's avatar
memleak  
Michael Niedermayer committed
109
    AVAES *a;
Michael Niedermayer's avatar
Michael Niedermayer committed
110 111
    int i, j, t, rconpointer = 0;
    uint8_t tk[8][4];
Michael Niedermayer's avatar
Michael Niedermayer committed
112 113
    int KC= key_bits/32;
    int rounds= KC + 6;
114 115
    uint8_t  log8[256];
    uint8_t alog8[512];
Michael Niedermayer's avatar
Michael Niedermayer committed
116 117 118 119 120 121 122 123 124 125 126 127 128

    if(!sbox[255]){
        j=1;
        for(i=0; i<255; i++){
            alog8[i]=
            alog8[i+255]= j;
            log8[j]= i;
            j^= j+j;
            if(j>255) j^= 0x11B;
        }
        log8[0]= 255;
        for(i=0; i<256; i++){
            j= i ? alog8[255-log8[i]] : 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
129 130
            j ^= (j<<1) ^ (j<<2) ^ (j<<3) ^ (j<<4);
            j = (j ^ (j>>8) ^ 99) & 255;
Michael Niedermayer's avatar
Michael Niedermayer committed
131 132 133
            inv_sbox[j]= i;
            sbox    [i]= j;
//            av_log(NULL, AV_LOG_ERROR, "%d, ", log8[i]);
134
            //FIXME multbl init
Michael Niedermayer's avatar
Michael Niedermayer committed
135 136 137
        }
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
138
    if(key_bits!=128 && key_bits!=192 && key_bits!=256)
Michael Niedermayer's avatar
Michael Niedermayer committed
139 140
        return NULL;

Michael Niedermayer's avatar
memleak  
Michael Niedermayer committed
141
    a= av_malloc(sizeof(AVAES));
Michael Niedermayer's avatar
Michael Niedermayer committed
142
    a->rounds= rounds;
Michael Niedermayer's avatar
memleak  
Michael Niedermayer committed
143

Michael Niedermayer's avatar
Michael Niedermayer committed
144 145
    memcpy(tk, key, KC*4);

Michael Niedermayer's avatar
Michael Niedermayer committed
146
    for(t= 0; t < (rounds+1)*4; ) {
Michael Niedermayer's avatar
Michael Niedermayer committed
147
        for(j = 0; j < KC && t < (rounds+1)*4; j++, t++)
Michael Niedermayer's avatar
memcpy  
Michael Niedermayer committed
148
            memcpy(a->round_key[0][t],  tk[j], 4);
Michael Niedermayer's avatar
Michael Niedermayer committed
149 150

        for(i = 0; i < 4; i++)
Michael Niedermayer's avatar
Michael Niedermayer committed
151
            tk[0][i] ^= sbox[tk[KC-1][(i+1)&3]];
Michael Niedermayer's avatar
Michael Niedermayer committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
        tk[0][0] ^= rcon[rconpointer++];

        for(j = 1; j < KC; j++){
            if(KC != 8 || j != KC/2)
                for(i = 0; i < 4; i++) tk[j][i] ^= tk[j-1][i];
            else
                for(i = 0; i < 4; i++)
                    tk[KC/2][i] ^= sbox[tk[KC/2 - 1][i]];
        }
    }
    return a;
}

#ifdef TEST

int main(){
    int i,j,k;
    AVAES *a= av_aes_init("PI=3.141592654..", 128);

    for(i=0; i<10000; i++){
    }
    return 0;
}
#endif