FFmpeg
aes.c
Go to the documentation of this file.
1 /*
2  * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * some optimization ideas from aes128.c by Reimar Doeffinger
5  *
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 <string.h>
24 
25 #include "config.h"
26 #include "aes.h"
27 #include "aes_internal.h"
28 #include "error.h"
29 #include "intreadwrite.h"
30 #include "macros.h"
31 #include "mem.h"
32 
33 const int av_aes_size= sizeof(AVAES);
34 
35 struct AVAES *av_aes_alloc(void)
36 {
37  return av_mallocz(sizeof(struct AVAES));
38 }
39 
40 static const uint8_t rcon[10] = {
41  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
42 };
43 
44 static uint8_t sbox[256];
45 static uint8_t inv_sbox[256];
46 #if CONFIG_SMALL
47 static uint32_t enc_multbl[1][256];
48 static uint32_t dec_multbl[1][256];
49 #else
50 static uint32_t enc_multbl[4][256];
51 static uint32_t dec_multbl[4][256];
52 #endif
53 
54 #if HAVE_BIGENDIAN
55 # define ROT(x, s) (((x) >> (s)) | ((x) << (32-(s))))
56 #else
57 # define ROT(x, s) (((x) << (s)) | ((x) >> (32-(s))))
58 #endif
59 
60 static inline void addkey(av_aes_block *dst, const av_aes_block *src,
61  const av_aes_block *round_key)
62 {
63  dst->u64[0] = src->u64[0] ^ round_key->u64[0];
64  dst->u64[1] = src->u64[1] ^ round_key->u64[1];
65 }
66 
67 static inline void addkey_s(av_aes_block *dst, const uint8_t *src,
68  const av_aes_block *round_key)
69 {
70  dst->u64[0] = AV_RN64(src) ^ round_key->u64[0];
71  dst->u64[1] = AV_RN64(src + 8) ^ round_key->u64[1];
72 }
73 
74 static inline void addkey_d(uint8_t *dst, const av_aes_block *src,
75  const av_aes_block *round_key)
76 {
77  AV_WN64(dst, src->u64[0] ^ round_key->u64[0]);
78  AV_WN64(dst + 8, src->u64[1] ^ round_key->u64[1]);
79 }
80 
81 static void subshift(av_aes_block s0[2], int s, const uint8_t *box)
82 {
83  unsigned char *s1_dst = (unsigned char*)s0[0].u8 + 3 - s;
84  const unsigned char *s1_src = s1_dst + sizeof(*s0);
85  unsigned char *s3_dst = (unsigned char*)s0[0].u8 + s + 1;
86  const unsigned char *s3_src = s3_dst + sizeof(*s0);
87 
88  s0[0].u8[ 0] = box[s0[1].u8[ 0]];
89  s0[0].u8[ 4] = box[s0[1].u8[ 4]];
90  s0[0].u8[ 8] = box[s0[1].u8[ 8]];
91  s0[0].u8[12] = box[s0[1].u8[12]];
92  s1_dst[ 0] = box[s1_src[ 4]];
93  s1_dst[ 4] = box[s1_src[ 8]];
94  s1_dst[ 8] = box[s1_src[12]];
95  s1_dst[12] = box[s1_src[ 0]];
96  s0[0].u8[ 2] = box[s0[1].u8[10]];
97  s0[0].u8[10] = box[s0[1].u8[ 2]];
98  s0[0].u8[ 6] = box[s0[1].u8[14]];
99  s0[0].u8[14] = box[s0[1].u8[ 6]];
100  s3_dst[ 0] = box[s3_src[12]];
101  s3_dst[12] = box[s3_src[ 8]];
102  s3_dst[ 8] = box[s3_src[ 4]];
103  s3_dst[ 4] = box[s3_src[ 0]];
104 }
105 
106 static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d)
107 {
108 #if CONFIG_SMALL
109  return multbl[0][a] ^ ROT(multbl[0][b], 8) ^ ROT(multbl[0][c], 16) ^ ROT(multbl[0][d], 24);
110 #else
111  return multbl[0][a] ^ multbl[1][b] ^ multbl[2][c] ^ multbl[3][d];
112 #endif
113 }
114 
115 static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3)
116 {
117  uint8_t (*src)[4] = state[1].u8x4;
118  state[0].u32[0] = mix_core(multbl, src[0][0], src[s1 ][1], src[2][2], src[s3 ][3]);
119  state[0].u32[1] = mix_core(multbl, src[1][0], src[s3 - 1][1], src[3][2], src[s1 - 1][3]);
120  state[0].u32[2] = mix_core(multbl, src[2][0], src[s3 ][1], src[0][2], src[s1 ][3]);
121  state[0].u32[3] = mix_core(multbl, src[3][0], src[s1 - 1][1], src[1][2], src[s3 - 1][3]);
122 }
123 
124 static inline void aes_crypt(AVAES *a, int s, const uint8_t *sbox,
125  uint32_t multbl[][256])
126 {
127  int r;
128 
129  for (r = a->rounds - 1; r > 0; r--) {
130  mix(a->state, multbl, 3 - s, 1 + s);
131  addkey(&a->state[1], &a->state[0], &a->round_key[r]);
132  }
133 
134  subshift(&a->state[0], s, sbox);
135 }
136 
137 static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
138  int count, uint8_t *iv, int rounds)
139 {
140  while (count--) {
141  addkey_s(&a->state[1], src, &a->round_key[rounds]);
142  if (iv)
143  addkey_s(&a->state[1], iv, &a->state[1]);
144  aes_crypt(a, 2, sbox, enc_multbl);
145  addkey_d(dst, &a->state[0], &a->round_key[0]);
146  if (iv)
147  memcpy(iv, dst, 16);
148  src += 16;
149  dst += 16;
150  }
151 }
152 
153 static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
154  int count, uint8_t *iv, int rounds)
155 {
156  while (count--) {
157  addkey_s(&a->state[1], src, &a->round_key[rounds]);
159  if (iv) {
160  addkey_s(&a->state[0], iv, &a->state[0]);
161  memcpy(iv, src, 16);
162  }
163  addkey_d(dst, &a->state[0], &a->round_key[0]);
164  src += 16;
165  dst += 16;
166  }
167 }
168 
169 void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src,
170  int count, uint8_t *iv, int decrypt)
171 {
172  a->crypt(a, dst, src, count, iv, a->rounds);
173 }
174 
175 static void init_multbl2(uint32_t tbl[][256], const int c[4],
176  const uint8_t *log8, const uint8_t *alog8,
177  const uint8_t *sbox)
178 {
179  int i;
180 
181  for (i = 0; i < 256; i++) {
182  int x = sbox[i];
183  if (x) {
184  int k, l, m, n;
185  x = log8[x];
186  k = alog8[x + log8[c[0]]];
187  l = alog8[x + log8[c[1]]];
188  m = alog8[x + log8[c[2]]];
189  n = alog8[x + log8[c[3]]];
190  tbl[0][i] = AV_NE(MKBETAG(k, l, m, n), MKTAG(k, l, m, n));
191 #if !CONFIG_SMALL
192  tbl[1][i] = ROT(tbl[0][i], 8);
193  tbl[2][i] = ROT(tbl[0][i], 16);
194  tbl[3][i] = ROT(tbl[0][i], 24);
195 #endif
196  }
197  }
198 }
199 
200 // this is based on the reference AES code by Paulo Barreto and Vincent Rijmen
201 int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
202 {
203  int i, j, t, rconpointer = 0;
204  uint8_t tk[8][4];
205  int KC = key_bits >> 5;
206  int rounds = KC + 6;
207  uint8_t log8[256];
208  uint8_t alog8[512];
209 
210  a->crypt = decrypt ? aes_decrypt : aes_encrypt;
211 
213  j = 1;
214  for (i = 0; i < 255; i++) {
215  alog8[i] = alog8[i + 255] = j;
216  log8[j] = i;
217  j ^= j + j;
218  if (j > 255)
219  j ^= 0x11B;
220  }
221  for (i = 0; i < 256; i++) {
222  j = i ? alog8[255 - log8[i]] : 0;
223  j ^= (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4);
224  j = (j ^ (j >> 8) ^ 99) & 255;
225  inv_sbox[j] = i;
226  sbox[i] = j;
227  }
228  init_multbl2(dec_multbl, (const int[4]) { 0xe, 0x9, 0xd, 0xb },
229  log8, alog8, inv_sbox);
230  init_multbl2(enc_multbl, (const int[4]) { 0x2, 0x1, 0x1, 0x3 },
231  log8, alog8, sbox);
232  }
233 
234  if (key_bits != 128 && key_bits != 192 && key_bits != 256)
235  return AVERROR(EINVAL);
236 
237  a->rounds = rounds;
238 
239  memcpy(tk, key, KC * 4);
240  memcpy(a->round_key[0].u8, key, KC * 4);
241 
242  for (t = KC * 4; t < (rounds + 1) * 16; t += KC * 4) {
243  for (i = 0; i < 4; i++)
244  tk[0][i] ^= sbox[tk[KC - 1][(i + 1) & 3]];
245  tk[0][0] ^= rcon[rconpointer++];
246 
247  for (j = 1; j < KC; j++) {
248  if (KC != 8 || j != KC >> 1)
249  for (i = 0; i < 4; i++)
250  tk[j][i] ^= tk[j - 1][i];
251  else
252  for (i = 0; i < 4; i++)
253  tk[j][i] ^= sbox[tk[j - 1][i]];
254  }
255 
256  memcpy((unsigned char*)a->round_key + t, tk, KC * 4);
257  }
258 
259  if (decrypt) {
260  for (i = 1; i < rounds; i++) {
261  av_aes_block tmp[3];
262  tmp[2] = a->round_key[i];
263  subshift(&tmp[1], 0, sbox);
264  mix(tmp, dec_multbl, 1, 3);
265  a->round_key[i] = tmp[0];
266  }
267  } else {
268  for (i = 0; i < (rounds + 1) >> 1; i++)
269  FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds - i]);
270  }
271 
272  return 0;
273 }
274 
sbox
static uint8_t sbox[256]
Definition: aes.c:44
av_aes_init
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
Initialize an AVAES context.
Definition: aes.c:201
r
const char * r
Definition: vf_curves.c:126
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
aes_crypt
static void aes_crypt(AVAES *a, int s, const uint8_t *sbox, uint32_t multbl[][256])
Definition: aes.c:124
av_aes_block::u64
uint64_t u64[2]
Definition: aes_internal.h:28
av_aes_size
const int av_aes_size
Definition: aes.c:33
AV_RN64
#define AV_RN64(p)
Definition: intreadwrite.h:366
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
b
#define b
Definition: input.c:41
init_multbl2
static void init_multbl2(uint32_t tbl[][256], const int c[4], const uint8_t *log8, const uint8_t *alog8, const uint8_t *sbox)
Definition: aes.c:175
AVAES::rounds
int rounds
Definition: aes_internal.h:39
s3
#define s3
Definition: regdef.h:40
macros.h
inv_sbox
static uint8_t inv_sbox[256]
Definition: aes.c:45
addkey
static void addkey(av_aes_block *dst, const av_aes_block *src, const av_aes_block *round_key)
Definition: aes.c:60
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_NE
#define AV_NE(be, le)
Definition: macros.h:33
addkey_s
static void addkey_s(av_aes_block *dst, const uint8_t *src, const av_aes_block *round_key)
Definition: aes.c:67
s1
#define s1
Definition: regdef.h:38
key
const char * key
Definition: hwcontext_opencl.c:189
av_aes_block
Definition: aes_internal.h:27
aes.h
mix
static void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3)
Definition: aes.c:115
av_aes_crypt
void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
Encrypt or decrypt a buffer using a previously initialized context.
Definition: aes.c:169
av_aes_alloc
struct AVAES * av_aes_alloc(void)
Allocate an AVAES context.
Definition: aes.c:35
state
static struct @385 state
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
error.h
ROT
#define ROT(x, s)
Definition: aes.c:57
AVAES::round_key
av_aes_block round_key[15]
Definition: aes_internal.h:37
aes_encrypt
static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int rounds)
Definition: aes.c:137
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
aes_decrypt
static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int rounds)
Definition: aes.c:153
dec_multbl
static uint32_t dec_multbl[4][256]
Definition: aes.c:51
aes_internal.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
AVAES
Definition: aes_internal.h:34
enc_multbl
static uint32_t enc_multbl[4][256]
Definition: aes.c:50
mem.h
rcon
static const uint8_t rcon[10]
Definition: aes.c:40
s0
#define s0
Definition: regdef.h:37
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
addkey_d
static void addkey_d(uint8_t *dst, const av_aes_block *src, const av_aes_block *round_key)
Definition: aes.c:74
d
d
Definition: ffmpeg_filter.c:409
AV_WN64
#define AV_WN64(p, v)
Definition: intreadwrite.h:378
MKTAG
#define MKTAG(a, b, c, d)
Definition: macros.h:55
subshift
static void subshift(av_aes_block s0[2], int s, const uint8_t *box)
Definition: aes.c:81
mix_core
static int mix_core(uint32_t multbl[][256], int a, int b, int c, int d)
Definition: aes.c:106