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