aes.c 5.13 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 82
}


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
83
            mix(a->state, dec_multbl);
Michael Niedermayer's avatar
Michael Niedermayer committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
        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
104
            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
105 106 107 108
    }
}

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

    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
130 131
            j ^= (j<<1) ^ (j<<2) ^ (j<<3) ^ (j<<4);
            j = (j ^ (j>>8) ^ 99) & 255;
Michael Niedermayer's avatar
Michael Niedermayer committed
132 133 134
            inv_sbox[j]= i;
            sbox    [i]= j;
//            av_log(NULL, AV_LOG_ERROR, "%d, ", log8[i]);
135
            //FIXME multbl init
Michael Niedermayer's avatar
Michael Niedermayer committed
136 137 138
        }
    }

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
147 148
    for(t= 0; t < (rounds+1)*4; ) {
        for(j = 0; (j < KC) && (t < (rounds+1)*4); j++, t++)
Michael Niedermayer's avatar
memcpy  
Michael Niedermayer committed
149
            memcpy(a->round_key[0][t],  tk[j], 4);
Michael Niedermayer's avatar
Michael Niedermayer committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

        for(i = 0; i < 4; i++)
                tk[0][i] ^= sbox[tk[KC-1][(i+1)&3]];
        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