cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
aes_modes.c
Go to the documentation of this file.
1 /*
2  ---------------------------------------------------------------------------
3  Copyright (c) 1998-2006, Brian Gladman, Worcester, UK. All rights reserved.
4 
5  LICENSE TERMS
6 
7  The free distribution and use of this software in both source and binary
8  form is allowed (with or without changes) provided that:
9 
10  1. distributions of this source code include the above copyright
11  notice, this list of conditions and the following disclaimer;
12 
13  2. distributions in binary form include the above copyright
14  notice, this list of conditions and the following disclaimer
15  in the documentation and/or other associated materials;
16 
17  3. the copyright holder's name is not used to endorse products
18  built using this software without specific written permission.
19 
20  ALTERNATIVELY, provided that this notice is retained in full, this product
21  may be distributed under the terms of the GNU General Public License (GPL),
22  in which case the provisions of the GPL apply INSTEAD OF those given above.
23 
24  DISCLAIMER
25 
26  This software is provided 'as is' with no explicit or implied warranties
27  in respect of its properties, including, but not limited to, correctness
28  and/or fitness for purpose.
29  ---------------------------------------------------------------------------
30  Issue 21/03/2007
31 
32  These subroutines implement multiple block AES modes for ECB, CBC, CFB,
33  OFB and CTR encryption, The code provides support for the VIA Advanced
34  Cryptography Engine (ACE).
35 
36  NOTE: In the following subroutines, the AES contexts (ctx) must be
37  16 byte aligned if VIA ACE is being used
38 */
39 
40 #include <string.h>
41 #include <assert.h>
42 
43 #include "crypt/aesopt.h" /* pcg */
44 
45 #if defined( AES_MODES )
46 #if defined(__cplusplus)
47 extern "C"
48 {
49 #endif
50 
51 #if defined( _MSC_VER ) && ( _MSC_VER > 800 )
52 #pragma intrinsic(memcpy)
53 #endif
54 
55 #define BFR_BLOCKS 8
56 
57 /* These values are used to detect long word alignment in order to */
58 /* speed up some buffer operations. This facility may not work on */
59 /* some machines so this define can be commented out if necessary */
60 
61 #define FAST_BUFFER_OPERATIONS
62 
63 #define lp32(x) ((uint_32t*)(x))
64 
65 #if defined( USE_VIA_ACE_IF_PRESENT )
66 
67 #include "crypt/aes_via_ace.h" /* pcg */
68 
69 #pragma pack(16)
70 
71 aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA;
72 aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA;
73 aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
74 aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA;
75 aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA;
76 aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
77 
78 /* NOTE: These control word macros must only be used after */
79 /* a key has been set up because they depend on key size */
80 
81 #if NEH_KEY_TYPE == NEH_LOAD
82 #define kd_adr(c) ((uint_8t*)(c)->ks)
83 #elif NEH_KEY_TYPE == NEH_GENERATE
84 #define kd_adr(c) ((uint_8t*)(c)->ks + (c)->inf.b[0])
85 #else
86 #define kd_adr(c) ((uint_8t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
87 #endif
88 
89 #else
90 
91 #define aligned_array(type, name, no, stride) type name[no]
92 #define aligned_auto(type, name, no, stride) type name[no]
93 
94 #endif
95 
96 #if defined( _MSC_VER ) && _MSC_VER > 1200
97 
98 #define via_cwd(cwd, ty, dir, len) \
99  unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
100 
101 #else
102 
103 #define via_cwd(cwd, ty, dir, len) \
104  aligned_auto(unsigned long, cwd, 4, 16); \
105  cwd[1] = cwd[2] = cwd[3] = 0; \
106  cwd[0] = neh_##dir##_##ty##_key(len)
107 
108 #endif
109 
110 /* test the code for detecting and setting pointer alignment */
111 
112 AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */
113 { uint_8t p[16];
114  uint_32t i, count_eq = 0, count_neq = 0;
115 
116  if(n < 4 || n > 16)
117  return EXIT_FAILURE;
118 
119  for(i = 0; i < n; ++i)
120  {
121  uint_8t *qf = ALIGN_FLOOR(p + i, n),
122  *qh = ALIGN_CEIL(p + i, n);
123 
124  if(qh == qf)
125  ++count_eq;
126  else if(qh == qf + n)
127  ++count_neq;
128  else
129  return EXIT_FAILURE;
130  }
131  return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
132 }
133 
135 {
136  ctx->inf.b[2] = 0;
137  return EXIT_SUCCESS;
138 }
139 
140 AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
141  int len, const aes_encrypt_ctx ctx[1])
142 { int nb = len >> 4;
143 
144  if(len & (AES_BLOCK_SIZE - 1))
145  return EXIT_FAILURE;
146 
147 #if defined( USE_VIA_ACE_IF_PRESENT )
148 
149  if(ctx->inf.b[1] == 0xff)
150  { uint_8t *ksp = (uint_8t*)(ctx->ks);
151  via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
152 
153  if(ALIGN_OFFSET( ctx, 16 ))
154  return EXIT_FAILURE;
155 
156  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
157  {
158  via_ecb_op5(ksp,cwd,ibuf,obuf,nb);
159  }
160  else
161  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
162  uint_8t *ip, *op;
163 
164  while(nb)
165  {
166  int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
167 
168  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
169  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
170 
171  if(ip != ibuf)
172  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
173 
174  via_ecb_op5(ksp,cwd,ip,op,m);
175 
176  if(op != obuf)
177  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
178 
179  ibuf += m * AES_BLOCK_SIZE;
180  obuf += m * AES_BLOCK_SIZE;
181  nb -= m;
182  }
183  }
184 
185  return EXIT_SUCCESS;
186  }
187 
188 #endif
189 
190 #if !defined( ASSUME_VIA_ACE_PRESENT )
191  while(nb--)
192  {
193  if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
194  return EXIT_FAILURE;
195  ibuf += AES_BLOCK_SIZE;
196  obuf += AES_BLOCK_SIZE;
197  }
198 #endif
199  return EXIT_SUCCESS;
200 }
201 
202 AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
203  int len, const aes_decrypt_ctx ctx[1])
204 { int nb = len >> 4;
205 
206  if(len & (AES_BLOCK_SIZE - 1))
207  return EXIT_FAILURE;
208 
209 #if defined( USE_VIA_ACE_IF_PRESENT )
210 
211  if(ctx->inf.b[1] == 0xff)
212  { uint_8t *ksp = kd_adr(ctx);
213  via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
214 
215  if(ALIGN_OFFSET( ctx, 16 ))
216  return EXIT_FAILURE;
217 
218  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
219  {
220  via_ecb_op5(ksp,cwd,ibuf,obuf,nb);
221  }
222  else
223  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
224  uint_8t *ip, *op;
225 
226  while(nb)
227  {
228  int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
229 
230  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
231  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
232 
233  if(ip != ibuf)
234  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
235 
236  via_ecb_op5(ksp,cwd,ip,op,m);
237 
238  if(op != obuf)
239  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
240 
241  ibuf += m * AES_BLOCK_SIZE;
242  obuf += m * AES_BLOCK_SIZE;
243  nb -= m;
244  }
245  }
246 
247  return EXIT_SUCCESS;
248  }
249 
250 #endif
251 
252 #if !defined( ASSUME_VIA_ACE_PRESENT )
253  while(nb--)
254  {
255  if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
256  return EXIT_FAILURE;
257  ibuf += AES_BLOCK_SIZE;
258  obuf += AES_BLOCK_SIZE;
259  }
260 #endif
261  return EXIT_SUCCESS;
262 }
263 
264 AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
265  int len, unsigned char *iv, const aes_encrypt_ctx ctx[1])
266 { int nb = len >> 4;
267 
268  if(len & (AES_BLOCK_SIZE - 1))
269  return EXIT_FAILURE;
270 
271 #if defined( USE_VIA_ACE_IF_PRESENT )
272 
273  if(ctx->inf.b[1] == 0xff)
274  { uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
275  aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
276  via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
277 
278  if(ALIGN_OFFSET( ctx, 16 ))
279  return EXIT_FAILURE;
280 
281  if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
282  {
283  ivp = liv;
284  memcpy(liv, iv, AES_BLOCK_SIZE);
285  }
286 
287  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
288  {
289  via_cbc_op7(ksp,cwd,ibuf,obuf,nb,ivp,ivp);
290  }
291  else
292  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
293  uint_8t *ip, *op;
294 
295  while(nb)
296  {
297  int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
298 
299  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
300  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
301 
302  if(ip != ibuf)
303  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
304 
305  via_cbc_op7(ksp,cwd,ip,op,m,ivp,ivp);
306 
307  if(op != obuf)
308  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
309 
310  ibuf += m * AES_BLOCK_SIZE;
311  obuf += m * AES_BLOCK_SIZE;
312  nb -= m;
313  }
314  }
315 
316  if(iv != ivp)
317  memcpy(iv, ivp, AES_BLOCK_SIZE);
318 
319  return EXIT_SUCCESS;
320  }
321 
322 #endif
323 
324 #if !defined( ASSUME_VIA_ACE_PRESENT )
325 # ifdef FAST_BUFFER_OPERATIONS
326  if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
327  while(nb--)
328  {
329  lp32(iv)[0] ^= lp32(ibuf)[0];
330  lp32(iv)[1] ^= lp32(ibuf)[1];
331  lp32(iv)[2] ^= lp32(ibuf)[2];
332  lp32(iv)[3] ^= lp32(ibuf)[3];
333  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
334  return EXIT_FAILURE;
335  memcpy(obuf, iv, AES_BLOCK_SIZE);
336  ibuf += AES_BLOCK_SIZE;
337  obuf += AES_BLOCK_SIZE;
338  }
339  else
340 # endif
341  while(nb--)
342  {
343  iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1];
344  iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3];
345  iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5];
346  iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7];
347  iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9];
348  iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11];
349  iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13];
350  iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15];
351  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
352  return EXIT_FAILURE;
353  memcpy(obuf, iv, AES_BLOCK_SIZE);
354  ibuf += AES_BLOCK_SIZE;
355  obuf += AES_BLOCK_SIZE;
356  }
357 #endif
358  return EXIT_SUCCESS;
359 }
360 
361 AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
362  int len, unsigned char *iv, const aes_decrypt_ctx ctx[1])
363 { unsigned char tmp[AES_BLOCK_SIZE];
364  int nb = len >> 4;
365 
366  if(len & (AES_BLOCK_SIZE - 1))
367  return EXIT_FAILURE;
368 
369 #if defined( USE_VIA_ACE_IF_PRESENT )
370 
371  if(ctx->inf.b[1] == 0xff)
372  { uint_8t *ksp = kd_adr(ctx), *ivp = iv;
373  aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
374  via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
375 
376  if(ALIGN_OFFSET( ctx, 16 ))
377  return EXIT_FAILURE;
378 
379  if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
380  {
381  ivp = liv;
382  memcpy(liv, iv, AES_BLOCK_SIZE);
383  }
384 
385  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
386  {
387  via_cbc_op6(ksp,cwd,ibuf,obuf,nb,ivp);
388  }
389  else
390  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
391  uint_8t *ip, *op;
392 
393  while(nb)
394  {
395  int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
396 
397  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
398  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
399 
400  if(ip != ibuf)
401  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
402 
403  via_cbc_op6(ksp,cwd,ip,op,m,ivp);
404 
405  if(op != obuf)
406  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
407 
408  ibuf += m * AES_BLOCK_SIZE;
409  obuf += m * AES_BLOCK_SIZE;
410  nb -= m;
411  }
412  }
413 
414  if(iv != ivp)
415  memcpy(iv, ivp, AES_BLOCK_SIZE);
416 
417  return EXIT_SUCCESS;
418  }
419 #endif
420 
421 #if !defined( ASSUME_VIA_ACE_PRESENT )
422 # ifdef FAST_BUFFER_OPERATIONS
423  if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
424  while(nb--)
425  {
426  memcpy(tmp, ibuf, AES_BLOCK_SIZE);
427  if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
428  return EXIT_FAILURE;
429  lp32(obuf)[0] ^= lp32(iv)[0];
430  lp32(obuf)[1] ^= lp32(iv)[1];
431  lp32(obuf)[2] ^= lp32(iv)[2];
432  lp32(obuf)[3] ^= lp32(iv)[3];
433  memcpy(iv, tmp, AES_BLOCK_SIZE);
434  ibuf += AES_BLOCK_SIZE;
435  obuf += AES_BLOCK_SIZE;
436  }
437  else
438 # endif
439  while(nb--)
440  {
441  memcpy(tmp, ibuf, AES_BLOCK_SIZE);
442  if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
443  return EXIT_FAILURE;
444  obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1];
445  obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3];
446  obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5];
447  obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7];
448  obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9];
449  obuf[10] ^= iv[10]; obuf[11] ^= iv[11];
450  obuf[12] ^= iv[12]; obuf[13] ^= iv[13];
451  obuf[14] ^= iv[14]; obuf[15] ^= iv[15];
452  memcpy(iv, tmp, AES_BLOCK_SIZE);
453  ibuf += AES_BLOCK_SIZE;
454  obuf += AES_BLOCK_SIZE;
455  }
456 #endif
457  return EXIT_SUCCESS;
458 }
459 
460 AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
461  int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
462 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
463 
464  if(b_pos) /* complete any partial block */
465  {
466  while(b_pos < AES_BLOCK_SIZE && cnt < len)
467  {
468  *obuf++ = iv[b_pos++] ^= *ibuf++;
469  cnt++;
470  }
471 
472  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
473  }
474 
475  if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
476  {
477 #if defined( USE_VIA_ACE_IF_PRESENT )
478 
479  if(ctx->inf.b[1] == 0xff)
480  { int m;
481  uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
482  aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
483  via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
484 
485  if(ALIGN_OFFSET( ctx, 16 ))
486  return EXIT_FAILURE;
487 
488  if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
489  {
490  ivp = liv;
491  memcpy(liv, iv, AES_BLOCK_SIZE);
492  }
493 
494  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
495  {
496  via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
497  ibuf += nb * AES_BLOCK_SIZE;
498  obuf += nb * AES_BLOCK_SIZE;
499  cnt += nb * AES_BLOCK_SIZE;
500  }
501  else /* input, output or both are unaligned */
502  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
503  uint_8t *ip, *op;
504 
505  while(nb)
506  {
507  m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
508 
509  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
510  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
511 
512  if(ip != ibuf)
513  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
514 
515  via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
516 
517  if(op != obuf)
518  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
519 
520  ibuf += m * AES_BLOCK_SIZE;
521  obuf += m * AES_BLOCK_SIZE;
522  cnt += m * AES_BLOCK_SIZE;
523  }
524  }
525 
526  if(ivp != iv)
527  memcpy(iv, ivp, AES_BLOCK_SIZE);
528  }
529 #else
530 # ifdef FAST_BUFFER_OPERATIONS
531  if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
532  while(cnt + AES_BLOCK_SIZE <= len)
533  {
534  assert(b_pos == 0);
535  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
536  return EXIT_FAILURE;
537  lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
538  lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
539  lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
540  lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
541  ibuf += AES_BLOCK_SIZE;
542  obuf += AES_BLOCK_SIZE;
543  cnt += AES_BLOCK_SIZE;
544  }
545  else
546 # endif
547  while(cnt + AES_BLOCK_SIZE <= len)
548  {
549  assert(b_pos == 0);
550  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
551  return EXIT_FAILURE;
552  obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];
553  obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];
554  obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];
555  obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];
556  obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];
557  obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];
558  obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];
559  obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];
560  ibuf += AES_BLOCK_SIZE;
561  obuf += AES_BLOCK_SIZE;
562  cnt += AES_BLOCK_SIZE;
563  }
564 #endif
565  }
566 
567  while(cnt < len)
568  {
569  if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
570  return EXIT_FAILURE;
571 
572  while(cnt < len && b_pos < AES_BLOCK_SIZE)
573  {
574  *obuf++ = iv[b_pos++] ^= *ibuf++;
575  cnt++;
576  }
577 
578  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
579  }
580 
581  ctx->inf.b[2] = (uint_8t)b_pos;
582  return EXIT_SUCCESS;
583 }
584 
585 AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
586  int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
587 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
588 
589  if(b_pos) /* complete any partial block */
590  { unsigned char t;
591 
592  while(b_pos < AES_BLOCK_SIZE && cnt < len)
593  {
594  t = *ibuf++;
595  *obuf++ = (unsigned char)(t ^ iv[b_pos]);
596  iv[b_pos++] = t;
597  cnt++;
598  }
599 
600  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
601  }
602 
603  if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
604  {
605 #if defined( USE_VIA_ACE_IF_PRESENT )
606 
607  if(ctx->inf.b[1] == 0xff)
608  { int m;
609  uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
610  aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
611  via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
612 
613  if(ALIGN_OFFSET( ctx, 16 ))
614  return EXIT_FAILURE;
615 
616  if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
617  {
618  ivp = liv;
619  memcpy(liv, iv, AES_BLOCK_SIZE);
620  }
621 
622  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
623  {
624  via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
625  ibuf += nb * AES_BLOCK_SIZE;
626  obuf += nb * AES_BLOCK_SIZE;
627  cnt += nb * AES_BLOCK_SIZE;
628  }
629  else /* input, output or both are unaligned */
630  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
631  uint_8t *ip, *op;
632 
633  while(nb)
634  {
635  m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
636 
637  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
638  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
639 
640  if(ip != ibuf)
641  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
642 
643  via_cfb_op6(ksp, cwd, ip, op, m, ivp);
644 
645  if(op != obuf)
646  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
647 
648  ibuf += m * AES_BLOCK_SIZE;
649  obuf += m * AES_BLOCK_SIZE;
650  cnt += m * AES_BLOCK_SIZE;
651  }
652  }
653 
654  if(ivp != iv)
655  memcpy(iv, ivp, AES_BLOCK_SIZE);
656  }
657 #else
658 # ifdef FAST_BUFFER_OPERATIONS
659  if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))
660  while(cnt + AES_BLOCK_SIZE <= len)
661  { uint_32t t;
662 
663  assert(b_pos == 0);
664  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
665  return EXIT_FAILURE;
666  t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
667  t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
668  t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
669  t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
670  ibuf += AES_BLOCK_SIZE;
671  obuf += AES_BLOCK_SIZE;
672  cnt += AES_BLOCK_SIZE;
673  }
674  else
675 # endif
676  while(cnt + AES_BLOCK_SIZE <= len)
677  { uint_8t t;
678 
679  assert(b_pos == 0);
680  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
681  return EXIT_FAILURE;
682  t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;
683  t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;
684  t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;
685  t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;
686  t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;
687  t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;
688  t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;
689  t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;
690  t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;
691  t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;
692  t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
693  t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
694  t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
695  t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
696  t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
697  t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
698  ibuf += AES_BLOCK_SIZE;
699  obuf += AES_BLOCK_SIZE;
700  cnt += AES_BLOCK_SIZE;
701  }
702 #endif
703  }
704 
705  while(cnt < len)
706  { unsigned char t;
707 
708  if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
709  return EXIT_FAILURE;
710 
711  while(cnt < len && b_pos < AES_BLOCK_SIZE)
712  {
713  t = *ibuf++;
714  *obuf++ = (unsigned char)(t ^ iv[b_pos]);
715  iv[b_pos++] = t;
716  cnt++;
717  }
718 
719  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
720  }
721 
722  ctx->inf.b[2] = (uint_8t)b_pos;
723  return EXIT_SUCCESS;
724 }
725 
726 AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
727  int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
728 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
729 
730  if(b_pos) /* complete any partial block */
731  {
732  while(b_pos < AES_BLOCK_SIZE && cnt < len)
733  {
734  *obuf++ = (unsigned char)(iv[b_pos++] ^ *ibuf++);
735  cnt++;
736  }
737 
738  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
739  }
740 
741  if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
742  {
743 #if defined( USE_VIA_ACE_IF_PRESENT )
744 
745  if(ctx->inf.b[1] == 0xff)
746  { int m;
747  uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
748  aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
749  via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
750 
751  if(ALIGN_OFFSET( ctx, 16 ))
752  return EXIT_FAILURE;
753 
754  if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
755  {
756  ivp = liv;
757  memcpy(liv, iv, AES_BLOCK_SIZE);
758  }
759 
760  if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
761  {
762  via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
763  ibuf += nb * AES_BLOCK_SIZE;
764  obuf += nb * AES_BLOCK_SIZE;
765  cnt += nb * AES_BLOCK_SIZE;
766  }
767  else /* input, output or both are unaligned */
768  { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
769  uint_8t *ip, *op;
770 
771  while(nb)
772  {
773  m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
774 
775  ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : (uint_8t*)ibuf);
776  op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
777 
778  if(ip != ibuf)
779  memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
780 
781  via_ofb_op6(ksp, cwd, ip, op, m, ivp);
782 
783  if(op != obuf)
784  memcpy(obuf, buf, m * AES_BLOCK_SIZE);
785 
786  ibuf += m * AES_BLOCK_SIZE;
787  obuf += m * AES_BLOCK_SIZE;
788  cnt += m * AES_BLOCK_SIZE;
789  }
790  }
791 
792  if(ivp != iv)
793  memcpy(iv, ivp, AES_BLOCK_SIZE);
794  }
795 #else
796 # ifdef FAST_BUFFER_OPERATIONS
797  if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
798  while(cnt + AES_BLOCK_SIZE <= len)
799  {
800  assert(b_pos == 0);
801  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
802  return EXIT_FAILURE;
803  lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
804  lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
805  lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
806  lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
807  ibuf += AES_BLOCK_SIZE;
808  obuf += AES_BLOCK_SIZE;
809  cnt += AES_BLOCK_SIZE;
810  }
811  else
812 # endif
813  while(cnt + AES_BLOCK_SIZE <= len)
814  {
815  assert(b_pos == 0);
816  if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
817  return EXIT_FAILURE;
818  obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];
819  obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];
820  obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];
821  obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];
822  obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];
823  obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];
824  obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];
825  obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];
826  ibuf += AES_BLOCK_SIZE;
827  obuf += AES_BLOCK_SIZE;
828  cnt += AES_BLOCK_SIZE;
829  }
830 #endif
831  }
832 
833  while(cnt < len)
834  {
835  if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
836  return EXIT_FAILURE;
837 
838  while(cnt < len && b_pos < AES_BLOCK_SIZE)
839  {
840  *obuf++ = (unsigned char)(iv[b_pos++] ^ *ibuf++);
841  cnt++;
842  }
843 
844  b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
845  }
846 
847  ctx->inf.b[2] = (uint_8t)b_pos;
848  return EXIT_SUCCESS;
849 }
850 
851 #define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
852 
853 AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
854  int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])
855 { unsigned char *ip;
856  int i, blen, b_pos = (int)(ctx->inf.b[2]);
857 
858 #if defined( USE_VIA_ACE_IF_PRESENT )
859  aligned_auto(uint_8t, buf, BFR_LENGTH, 16);
860  if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))
861  return EXIT_FAILURE;
862 #else
863  uint_8t buf[BFR_LENGTH];
864 #endif
865 
866  if(b_pos)
867  {
868  memcpy(buf, cbuf, AES_BLOCK_SIZE);
869  if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
870  return EXIT_FAILURE;
871  while(b_pos < AES_BLOCK_SIZE && len)
872  {
873  *obuf++ = (unsigned char)(*ibuf++ ^ buf[b_pos++]);
874  --len;
875  }
876 
877  if(len)
878  ctr_inc(cbuf), b_pos = 0;
879  }
880 
881  while(len)
882  {
883  blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
884 
885  for(i = 0, ip = buf; i < (blen >> 4); ++i)
886  {
887  memcpy(ip, cbuf, AES_BLOCK_SIZE);
888  ctr_inc(cbuf);
889  ip += AES_BLOCK_SIZE;
890  }
891 
892  if(blen & (AES_BLOCK_SIZE - 1))
893  memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
894 
895 #if defined( USE_VIA_ACE_IF_PRESENT )
896  if(ctx->inf.b[1] == 0xff)
897  {
898  via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
899  via_ecb_op5((ctx->ks),cwd,buf,buf,i);
900  }
901  else
902 #endif
903  if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
904  return EXIT_FAILURE;
905 
906  i = 0; ip = buf;
907 # ifdef FAST_BUFFER_OPERATIONS
908  if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))
909  while(i + AES_BLOCK_SIZE <= blen)
910  {
911  lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
912  lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
913  lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
914  lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
915  i += AES_BLOCK_SIZE;
916  ip += AES_BLOCK_SIZE;
917  ibuf += AES_BLOCK_SIZE;
918  obuf += AES_BLOCK_SIZE;
919  }
920  else
921 #endif
922  while(i + AES_BLOCK_SIZE <= blen)
923  {
924  obuf[ 0] = (unsigned char)(ibuf[ 0] ^ ip[ 0]);
925  obuf[ 1] = (unsigned char)(ibuf[ 1] ^ ip[ 1]);
926  obuf[ 2] = (unsigned char)(ibuf[ 2] ^ ip[ 2]);
927  obuf[ 3] = (unsigned char)(ibuf[ 3] ^ ip[ 3]);
928  obuf[ 4] = (unsigned char)(ibuf[ 4] ^ ip[ 4]);
929  obuf[ 5] = (unsigned char)(ibuf[ 5] ^ ip[ 5]);
930  obuf[ 6] = (unsigned char)(ibuf[ 6] ^ ip[ 6]);
931  obuf[ 7] = (unsigned char)(ibuf[ 7] ^ ip[ 7]);
932  obuf[ 8] = (unsigned char)(ibuf[ 8] ^ ip[ 8]);
933  obuf[ 9] = (unsigned char)(ibuf[ 9] ^ ip[ 9]);
934  obuf[10] = (unsigned char)(ibuf[10] ^ ip[10]);
935  obuf[11] = (unsigned char)(ibuf[11] ^ ip[11]);
936  obuf[12] = (unsigned char)(ibuf[12] ^ ip[12]);
937  obuf[13] = (unsigned char)(ibuf[13] ^ ip[13]);
938  obuf[14] = (unsigned char)(ibuf[14] ^ ip[14]);
939  obuf[15] = (unsigned char)(ibuf[15] ^ ip[15]);
940  i += AES_BLOCK_SIZE;
941  ip += AES_BLOCK_SIZE;
942  ibuf += AES_BLOCK_SIZE;
943  obuf += AES_BLOCK_SIZE;
944  }
945 
946  while(i++ < blen)
947  *obuf++ = (unsigned char)(*ibuf++ ^ ip[b_pos++]);
948  }
949 
950  ctx->inf.b[2] = (uint_8t)b_pos;
951  return EXIT_SUCCESS;
952 }
953 
954 #if defined(__cplusplus)
955 }
956 #endif
957 #endif