Mercurial > libavutil.hg
annotate aes.c @ 510:b7593ce78422 libavutil
Make av_fifo*_read() ignore the available amount of data.
This is more efficient as in practice the check is redundant most of the
time. Callers which do not know if enough data is available have to check
it with av_fifo_size(). Doing the check in *read() means the caller has
no choice to skip the check when its known to be redundant.
Also the return value was never documented in a public header so
changing it should not break the API. Besides this fixes the case where
read() failed on a 100% full fifo.
author | michael |
---|---|
date | Sun, 25 May 2008 22:20:39 +0000 |
parents | cf0184d7d6d7 |
children | 880c6441f56a |
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]; | |
169 | 42 #ifdef CONFIG_SMALL |
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 |
214 | 50 static inline void addkey(uint64_t dst[2], uint64_t src[2], uint64_t round_key[2]){ |
51 dst[0] = src[0] ^ round_key[0]; | |
52 dst[1] = src[1] ^ round_key[1]; | |
164 | 53 } |
54 | |
213
e50daf73d26c
change subshift a little, this reduces the object size a litlle
michael
parents:
212
diff
changeset
|
55 static void subshift(uint8_t s0[2][16], int s, uint8_t *box){ |
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){ |
169 | 65 #ifdef 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 |
216 | 80 static inline void crypt(AVAES *a, int s, uint8_t *sbox, 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 | |
221 | 90 void av_aes_crypt(AVAES *a, uint8_t *dst, 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 | |
195 | 111 static void init_multbl2(uint8_t tbl[1024], int c[4], uint8_t *log8, uint8_t *alog8, 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 } | |
199 | 117 #ifndef 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 } | |
184 | 149 init_multbl2(dec_multbl[0], (int[4]){0xe, 0x9, 0xd, 0xb}, log8, alog8, inv_sbox); |
183 | 150 init_multbl2(enc_multbl[0], (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 | |
207
b5ff46799eea
move #include log.h into the selftesting code where it belongs
michael
parents:
206
diff
changeset
|
195 #include "log.h" |
164 | 196 |
423
cf0184d7d6d7
Fix test program compilation, random() needs to be undefined.
diego
parents:
404
diff
changeset
|
197 #undef random |
cf0184d7d6d7
Fix test program compilation, random() needs to be undefined.
diego
parents:
404
diff
changeset
|
198 |
404 | 199 int main(void){ |
195 | 200 int i,j; |
206 | 201 AVAES ae, ad, b; |
198 | 202 uint8_t rkey[2][16]= { |
203 {0}, | |
204 {0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59}}; | |
205 uint8_t pt[16], rpt[2][16]= { | |
206 {0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad, 0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3}, | |
207 {0}}; | |
208 uint8_t rct[2][16]= { | |
209 {0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7, 0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf}, | |
210 {0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65}}; | |
214 | 211 uint8_t temp[16]; |
164 | 212 |
206 | 213 av_aes_init(&ae, "PI=3.141592654..", 128, 0); |
214 av_aes_init(&ad, "PI=3.141592654..", 128, 1); | |
179 | 215 av_log_level= AV_LOG_DEBUG; |
216 | |
198 | 217 for(i=0; i<2; i++){ |
206 | 218 av_aes_init(&b, rkey[i], 128, 1); |
221 | 219 av_aes_crypt(&b, temp, rct[i], 1, NULL, 1); |
198 | 220 for(j=0; j<16; j++) |
214 | 221 if(rpt[i][j] != temp[j]) |
222 av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n", j, rpt[i][j], temp[j]); | |
198 | 223 } |
183 | 224 |
164 | 225 for(i=0; i<10000; i++){ |
178 | 226 for(j=0; j<16; j++){ |
227 pt[j]= random(); | |
228 } | |
179 | 229 {START_TIMER |
221 | 230 av_aes_crypt(&ae, temp, pt, 1, NULL, 0); |
178 | 231 if(!(i&(i-1))) |
214 | 232 av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n", temp[0], temp[5], temp[10], temp[15]); |
221 | 233 av_aes_crypt(&ad, temp, temp, 1, NULL, 1); |
179 | 234 STOP_TIMER("aes")} |
178 | 235 for(j=0; j<16; j++){ |
214 | 236 if(pt[j] != temp[j]){ |
237 av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n", i,j, pt[j], temp[j]); | |
178 | 238 } |
239 } | |
164 | 240 } |
241 return 0; | |
242 } | |
243 #endif |