Commit | Line | Data |
---|---|---|
3306dfd5 MN |
1 | /* |
2 | * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at> | |
3 | * | |
4 | * This file is part of FFmpeg. | |
5 | * | |
6 | * FFmpeg is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2.1 of the License, or (at your option) any later version. | |
10 | * | |
11 | * FFmpeg is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with FFmpeg; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
20 | ||
21 | #include "common.h" | |
22 | #include "log.h" | |
23 | #include "aes.h" | |
24 | ||
25 | typedef struct AVAES{ | |
26 | uint8_t state[4][4]; | |
27 | uint8_t round_key[15][4][4]; | |
28 | int rounds; | |
29 | }AVAES; | |
30 | ||
31 | static const uint8_t rcon[30] = { | |
32 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, | |
33 | 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, | |
34 | 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, | |
35 | 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 | |
36 | }; | |
37 | ||
38 | static uint8_t log8[256]; | |
39 | static uint8_t alog8[512]; | |
40 | static uint8_t sbox[256]; | |
41 | static uint8_t inv_sbox[256]; | |
42 | ||
43 | static inline void addkey(uint32_t state[4], uint32_t round_key[4]){ | |
44 | int i; | |
45 | for(i=0; i<4; i++) | |
46 | state[i] ^= round_key[i]; //partial memory stall? FIXME benchmark | |
47 | } | |
48 | ||
49 | #define SUBSHIFT0(s, box) s[0]=box[s[ 0]]; s[ 4]=box[s[ 4]]; s[ 8]=box[s[ 8]]; s[12]=box[s[12]]; | |
50 | #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]; | |
51 | #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]; | |
52 | #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]; | |
53 | ||
54 | static inline int mul(int a, int b){ | |
55 | if(a==255) return 0; | |
56 | else return alog8[a+b]; | |
57 | } | |
58 | ||
59 | static inline void mix(uint8_t state[4][4], int c0, int c1, int c2, int c3){ | |
60 | uint8_t tmp[4][4]; | |
61 | int i, j; | |
62 | ||
63 | for(i=0; i<16; i++) | |
64 | tmp[0][i]= log8[ state[0][i] ]; | |
65 | for(j=0; j<4; j++) | |
66 | for(i=0; i<4; i++) | |
67 | state[j][i]= mul( tmp[j][ i ], c0 ) | |
68 | ^mul( tmp[j][(i+ 1)&3], c1 ) | |
69 | ^mul( tmp[j][(i+ 2)&3], c2 ) | |
70 | ^mul( tmp[j][(i+ 3)&3], c3 ); | |
71 | } | |
72 | ||
73 | ||
74 | void av_aes_decrypt(AVAES *a){ | |
75 | int t, r; | |
76 | ||
77 | for(r=a->rounds-1; r>=0; r--){ | |
78 | if(r==a->rounds-1) | |
79 | addkey(a->state, a->round_key[r+1]); | |
80 | else | |
81 | mix(a->state, log8[0xe], log8[0xb], log8[0xd], log8[9]); //FIXME replace log8 by const | |
82 | SUBSHIFT0((a->state[0]+0), inv_sbox) | |
83 | SUBSHIFT3((a->state[0]+1), inv_sbox) | |
84 | SUBSHIFT2((a->state[0]+2), inv_sbox) | |
85 | SUBSHIFT1((a->state[0]+3), inv_sbox) | |
86 | addkey(a->state, a->round_key[r]); | |
87 | } | |
88 | } | |
89 | ||
90 | void av_aes_encrypt(AVAES *a){ | |
91 | int r, t; | |
92 | ||
93 | for(r=0; r<a->rounds; r++){ | |
94 | addkey(a->state, a->round_key[r]); | |
95 | SUBSHIFT0((a->state[0]+0), sbox) | |
96 | SUBSHIFT1((a->state[0]+1), sbox) | |
97 | SUBSHIFT2((a->state[0]+2), sbox) | |
98 | SUBSHIFT3((a->state[0]+3), sbox) | |
99 | if(r==a->rounds-1) | |
100 | addkey(a->state, a->round_key[r+1]); | |
101 | else | |
102 | mix(a->state, log8[2], log8[3], 0, 0); //FIXME replace log8 by const / optimze mix as this can be simplified alot | |
103 | } | |
104 | } | |
105 | ||
106 | // this is based on the reference AES code by Paulo Barreto and Vincent Rijmen | |
107 | AVAES *av_aes_init(uint8_t *key, int keyBits) { | |
108 | AVAES *a= av_malloc(sizeof(AVAES)); | |
109 | int i, j, t, rconpointer = 0; | |
110 | uint8_t tk[8][4]; | |
111 | int KC= keyBits/32; | |
112 | int ROUNDS= KC + 6; | |
113 | ||
114 | if(!sbox[255]){ | |
115 | j=1; | |
116 | for(i=0; i<255; i++){ | |
117 | alog8[i]= | |
118 | alog8[i+255]= j; | |
119 | log8[j]= i; | |
120 | j^= j+j; | |
121 | if(j>255) j^= 0x11B; | |
122 | } | |
123 | log8[0]= 255; | |
124 | for(i=0; i<256; i++){ | |
125 | j= i ? alog8[255-log8[i]] : 0; | |
126 | j ^= (j<<1) ^ (j<<2) ^ (j<<3) ^ (j<<4) | |
127 | ^(j>>7) ^ (j>>6) ^ (j>>5) ^ (j>>4) ^ 99; | |
128 | j&=255; | |
129 | inv_sbox[j]= i; | |
130 | sbox [i]= j; | |
131 | // av_log(NULL, AV_LOG_ERROR, "%d, ", log8[i]); | |
132 | } | |
133 | } | |
134 | ||
135 | a->rounds= ROUNDS; | |
136 | ||
137 | if(keyBits!=128 && keyBits!=192 && keyBits!=256) | |
138 | return NULL; | |
139 | ||
140 | memcpy(tk, key, KC*4); | |
141 | ||
142 | for(t= 0; t < (ROUNDS+1)*4; ) { | |
143 | for(j = 0; (j < KC) && (t < (ROUNDS+1)*4); j++, t++) | |
144 | for(i = 0; i < 4; i++) | |
145 | a->round_key[0][t][i] = tk[j][i]; | |
146 | ||
147 | for(i = 0; i < 4; i++) | |
148 | tk[0][i] ^= sbox[tk[KC-1][(i+1)&3]]; | |
149 | tk[0][0] ^= rcon[rconpointer++]; | |
150 | ||
151 | for(j = 1; j < KC; j++){ | |
152 | if(KC != 8 || j != KC/2) | |
153 | for(i = 0; i < 4; i++) tk[j][i] ^= tk[j-1][i]; | |
154 | else | |
155 | for(i = 0; i < 4; i++) | |
156 | tk[KC/2][i] ^= sbox[tk[KC/2 - 1][i]]; | |
157 | } | |
158 | } | |
159 | return a; | |
160 | } | |
161 | ||
162 | #ifdef TEST | |
163 | ||
164 | int main(){ | |
165 | int i,j,k; | |
166 | AVAES *a= av_aes_init("PI=3.141592654..", 128); | |
167 | ||
168 | for(i=0; i<10000; i++){ | |
169 | } | |
170 | return 0; | |
171 | } | |
172 | #endif |