Mercurial > libavutil.hg
annotate aes.c @ 822:a1680eca3e52 libavutil
DECLARE_ALIGNED macro for TMS470 compiler
This compiler supports gcc-style alignment attributes for struct,
but not for global variables. For the latter, alignment can be
specified with a pragma, which does not work for struct members or
local variables. By using both pragma and attribute, one or the
other will always take effect.
Unfortunately, no means exists for aligning stack variables.
author | mru |
---|---|
date | Fri, 22 Jan 2010 03:25:25 +0000 |
parents | 5d344280a1f8 |
children | 567489a515b2 |
rev | line source |
---|---|
164 | 1 /* |
194
3d5efe2de0ae
seems i didnt copy anything from aes128.c so this should be more correct ?
michael
parents:
193
diff
changeset
|
2 * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at> |
164 | 3 * |
354 | 4 * some optimization ideas from aes128.c by Reimar Doeffinger |
5 * | |
164 | 6 * This file is part of FFmpeg. |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 #include "common.h" | |
24 #include "aes.h" | |
25 | |
26 typedef struct AVAES{ | |
368
99c56fd6e3f4
Document aes init code writing on purpose beyond round_key array into state array.
reimar
parents:
354
diff
changeset
|
27 // Note: round_key[16] is accessed in the init code, but this only |
99c56fd6e3f4
Document aes init code writing on purpose beyond round_key array into state array.
reimar
parents:
354
diff
changeset
|
28 // overwrites state, which does not matter (see also r7471). |
189 | 29 uint8_t round_key[15][4][4]; |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
30 uint8_t state[2][4][4]; |
164 | 31 int rounds; |
32 }AVAES; | |
33 | |
206 | 34 const int av_aes_size= sizeof(AVAES); |
35 | |
192 | 36 static const uint8_t rcon[10] = { |
37 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 | |
164 | 38 }; |
39 | |
40 static uint8_t sbox[256]; | |
41 static uint8_t inv_sbox[256]; | |
603 | 42 #if CONFIG_SMALL |
169 | 43 static uint32_t enc_multbl[1][256]; |
44 static uint32_t dec_multbl[1][256]; | |
45 #else | |
46 static uint32_t enc_multbl[4][256]; | |
47 static uint32_t dec_multbl[4][256]; | |
48 #endif | |
164 | 49 |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
50 static inline void addkey(uint64_t dst[2], const uint64_t src[2], const uint64_t round_key[2]){ |
214 | 51 dst[0] = src[0] ^ round_key[0]; |
52 dst[1] = src[1] ^ round_key[1]; | |
164 | 53 } |
54 | |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
55 static void subshift(uint8_t s0[2][16], int s, const uint8_t *box){ |
213
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
56 uint8_t (*s1)[16]= s0[0] - s; |
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
57 uint8_t (*s3)[16]= s0[0] + s; |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
58 s0[0][0]=box[s0[1][ 0]]; s0[0][ 4]=box[s0[1][ 4]]; s0[0][ 8]=box[s0[1][ 8]]; s0[0][12]=box[s0[1][12]]; |
213
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
59 s1[0][3]=box[s1[1][ 7]]; s1[0][ 7]=box[s1[1][11]]; s1[0][11]=box[s1[1][15]]; s1[0][15]=box[s1[1][ 3]]; |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
60 s0[0][2]=box[s0[1][10]]; s0[0][10]=box[s0[1][ 2]]; s0[0][ 6]=box[s0[1][14]]; s0[0][14]=box[s0[1][ 6]]; |
213
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
61 s3[0][1]=box[s3[1][13]]; s3[0][13]=box[s3[1][ 9]]; s3[0][ 9]=box[s3[1][ 5]]; s3[0][ 5]=box[s3[1][ 1]]; |
209 | 62 } |
183 | 63 |
220 | 64 static inline int mix_core(uint32_t multbl[4][256], int a, int b, int c, int d){ |
603 | 65 #if CONFIG_SMALL |
220 | 66 #define ROT(x,s) ((x<<s)|(x>>(32-s))) |
67 return multbl[0][a] ^ ROT(multbl[0][b], 8) ^ ROT(multbl[0][c], 16) ^ ROT(multbl[0][d], 24); | |
169 | 68 #else |
220 | 69 return multbl[0][a] ^ multbl[1][b] ^ multbl[2][c] ^ multbl[3][d]; |
169 | 70 #endif |
164 | 71 } |
209 | 72 |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
73 static inline void mix(uint8_t state[2][4][4], uint32_t multbl[4][256], int s1, int s3){ |
220 | 74 ((uint32_t *)(state))[0] = mix_core(multbl, state[1][0][0], state[1][s1 ][1], state[1][2][2], state[1][s3 ][3]); |
75 ((uint32_t *)(state))[1] = mix_core(multbl, state[1][1][0], state[1][s3-1][1], state[1][3][2], state[1][s1-1][3]); | |
76 ((uint32_t *)(state))[2] = mix_core(multbl, state[1][2][0], state[1][s3 ][1], state[1][0][2], state[1][s1 ][3]); | |
77 ((uint32_t *)(state))[3] = mix_core(multbl, state[1][3][0], state[1][s1-1][1], state[1][1][2], state[1][s3-1][3]); | |
209 | 78 } |
164 | 79 |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
80 static inline void crypt(AVAES *a, int s, const uint8_t *sbox, const uint32_t *multbl){ |
210 | 81 int r; |
164 | 82 |
214 | 83 for(r=a->rounds-1; r>0; r--){ |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
84 mix(a->state, multbl, 3-s, 1+s); |
214 | 85 addkey(a->state[1], a->state[0], a->round_key[r]); |
164 | 86 } |
213
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
87 subshift(a->state[0][0], s, sbox); |
164 | 88 } |
89 | |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
90 void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt){ |
216 | 91 while(count--){ |
92 addkey(a->state[1], src, a->round_key[a->rounds]); | |
93 if(decrypt) { | |
94 crypt(a, 0, inv_sbox, dec_multbl); | |
95 if(iv){ | |
96 addkey(a->state[0], a->state[0], iv); | |
97 memcpy(iv, src, 16); | |
98 } | |
99 addkey(dst, a->state[0], a->round_key[0]); | |
100 }else{ | |
101 if(iv) addkey(a->state[1], a->state[1], iv); | |
102 crypt(a, 2, sbox, enc_multbl); | |
103 addkey(dst, a->state[0], a->round_key[0]); | |
104 if(iv) memcpy(iv, dst, 16); | |
105 } | |
106 src+=16; | |
107 dst+=16; | |
108 } | |
178 | 109 } |
110 | |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
111 static void init_multbl2(uint8_t tbl[1024], const int c[4], const uint8_t *log8, const uint8_t *alog8, const uint8_t *sbox){ |
200 | 112 int i, j; |
183 | 113 for(i=0; i<1024; i++){ |
204
b7ac7733b2f4
replace / by >> this makes the .o ~150 bytes smaller
michael
parents:
203
diff
changeset
|
114 int x= sbox[i>>2]; |
183 | 115 if(x) tbl[i]= alog8[ log8[x] + log8[c[i&3]] ]; |
116 } | |
603 | 117 #if !CONFIG_SMALL |
200 | 118 for(j=256; j<1024; j++) |
119 for(i=0; i<4; i++) | |
120 tbl[4*j+i]= tbl[4*j + ((i-1)&3) - 1024]; | |
199 | 121 #endif |
183 | 122 } |
123 | |
164 | 124 // this is based on the reference AES code by Paulo Barreto and Vincent Rijmen |
241 | 125 int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) { |
164 | 126 int i, j, t, rconpointer = 0; |
127 uint8_t tk[8][4]; | |
204
b7ac7733b2f4
replace / by >> this makes the .o ~150 bytes smaller
michael
parents:
203
diff
changeset
|
128 int KC= key_bits>>5; |
167 | 129 int rounds= KC + 6; |
169 | 130 uint8_t log8[256]; |
131 uint8_t alog8[512]; | |
164 | 132 |
337 | 133 if(!enc_multbl[0][sizeof(enc_multbl)/sizeof(enc_multbl[0][0])-1]){ |
164 | 134 j=1; |
135 for(i=0; i<255; i++){ | |
136 alog8[i]= | |
137 alog8[i+255]= j; | |
138 log8[j]= i; | |
139 j^= j+j; | |
140 if(j>255) j^= 0x11B; | |
141 } | |
142 for(i=0; i<256; i++){ | |
143 j= i ? alog8[255-log8[i]] : 0; | |
165 | 144 j ^= (j<<1) ^ (j<<2) ^ (j<<3) ^ (j<<4); |
145 j = (j ^ (j>>8) ^ 99) & 255; | |
164 | 146 inv_sbox[j]= i; |
147 sbox [i]= j; | |
148 } | |
635
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
149 init_multbl2(dec_multbl[0], (const int[4]){0xe, 0x9, 0xd, 0xb}, log8, alog8, inv_sbox); |
0a51400a64c9
Add "const" to AES function arguments where possible without generating
reimar
parents:
603
diff
changeset
|
150 init_multbl2(enc_multbl[0], (const int[4]){0x2, 0x1, 0x1, 0x3}, log8, alog8, sbox); |
164 | 151 } |
152 | |
167 | 153 if(key_bits!=128 && key_bits!=192 && key_bits!=256) |
206 | 154 return -1; |
164 | 155 |
167 | 156 a->rounds= rounds; |
166 | 157 |
164 | 158 memcpy(tk, key, KC*4); |
159 | |
219 | 160 for(t= 0; t < (rounds+1)*16;) { |
161 memcpy(a->round_key[0][0]+t, tk, KC*4); | |
162 t+= KC*4; | |
164 | 163 |
164 for(i = 0; i < 4; i++) | |
173 | 165 tk[0][i] ^= sbox[tk[KC-1][(i+1)&3]]; |
164 | 166 tk[0][0] ^= rcon[rconpointer++]; |
167 | |
168 for(j = 1; j < KC; j++){ | |
204
b7ac7733b2f4
replace / by >> this makes the .o ~150 bytes smaller
michael
parents:
203
diff
changeset
|
169 if(KC != 8 || j != KC>>1) |
175 | 170 for(i = 0; i < 4; i++) tk[j][i] ^= tk[j-1][i]; |
164 | 171 else |
175 | 172 for(i = 0; i < 4; i++) tk[j][i] ^= sbox[tk[j-1][i]]; |
164 | 173 } |
174 } | |
184 | 175 |
189 | 176 if(decrypt){ |
190 | 177 for(i=1; i<rounds; i++){ |
215 | 178 uint8_t tmp[3][16]; |
179 memcpy(tmp[2], a->round_key[i][0], 16); | |
180 subshift(tmp[1], 0, sbox); | |
212
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
181 mix(tmp, dec_multbl, 1, 3); |
d31d4880105e
use 2 state arrays so that fewer temporary variables are needed
michael
parents:
211
diff
changeset
|
182 memcpy(a->round_key[i][0], tmp[0], 16); |
190 | 183 } |
197 | 184 }else{ |
204
b7ac7733b2f4
replace / by >> this makes the .o ~150 bytes smaller
michael
parents:
203
diff
changeset
|
185 for(i=0; i<(rounds+1)>>1; i++){ |
197 | 186 for(j=0; j<16; j++) |
187 FFSWAP(int, a->round_key[i][0][j], a->round_key[rounds-i][0][j]); | |
188 } | |
187 | 189 } |
184 | 190 |
206 | 191 return 0; |
164 | 192 } |
193 | |
194 #ifdef TEST | |
701
ae6e96434bec
Replace random() usage in test programs by av_lfg_*().
diego
parents:
698
diff
changeset
|
195 #include "lfg.h" |
207
b5ff46799eea
move #include log.h into the selftesting code where it belongs
michael
parents:
206
diff
changeset
|
196 #include "log.h" |
164 | 197 |
404 | 198 int main(void){ |
195 | 199 int i,j; |
206 | 200 AVAES ae, ad, b; |
198 | 201 uint8_t rkey[2][16]= { |
202 {0}, | |
203 {0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59}}; | |
204 uint8_t pt[16], rpt[2][16]= { | |
205 {0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad, 0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3}, | |
206 {0}}; | |
207 uint8_t rct[2][16]= { | |
208 {0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7, 0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf}, | |
209 {0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65}}; | |
214 | 210 uint8_t temp[16]; |
726
5d344280a1f8
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
701
diff
changeset
|
211 AVLFG prng; |
164 | 212 |
206 | 213 av_aes_init(&ae, "PI=3.141592654..", 128, 0); |
214 av_aes_init(&ad, "PI=3.141592654..", 128, 1); | |
698
8e9c6361e909
Make AES test program compile again: Setting the av_log_level variable
diego
parents:
635
diff
changeset
|
215 av_log_set_level(AV_LOG_DEBUG); |
726
5d344280a1f8
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
701
diff
changeset
|
216 av_lfg_init(&prng, 1); |
179 | 217 |
198 | 218 for(i=0; i<2; i++){ |
206 | 219 av_aes_init(&b, rkey[i], 128, 1); |
221 | 220 av_aes_crypt(&b, temp, rct[i], 1, NULL, 1); |
198 | 221 for(j=0; j<16; j++) |
214 | 222 if(rpt[i][j] != temp[j]) |
223 av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n", j, rpt[i][j], temp[j]); | |
198 | 224 } |
183 | 225 |
164 | 226 for(i=0; i<10000; i++){ |
178 | 227 for(j=0; j<16; j++){ |
726
5d344280a1f8
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
701
diff
changeset
|
228 pt[j] = av_lfg_get(&prng); |
178 | 229 } |
179 | 230 {START_TIMER |
221 | 231 av_aes_crypt(&ae, temp, pt, 1, NULL, 0); |
178 | 232 if(!(i&(i-1))) |
214 | 233 av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n", temp[0], temp[5], temp[10], temp[15]); |
221 | 234 av_aes_crypt(&ad, temp, temp, 1, NULL, 1); |
179 | 235 STOP_TIMER("aes")} |
178 | 236 for(j=0; j<16; j++){ |
214 | 237 if(pt[j] != temp[j]){ |
238 av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n", i,j, pt[j], temp[j]); | |
178 | 239 } |
240 } | |
164 | 241 } |
242 return 0; | |
243 } | |
244 #endif |