2 ---------------------------------------------------------------------------
\r
3 Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
\r
7 The redistribution and use of this software (with or without changes)
\r
8 is allowed without the payment of fees or royalties provided that:
\r
10 1. source code distributions include the above copyright notice, this
\r
11 list of conditions and the following disclaimer;
\r
13 2. binary distributions include the above copyright notice, this list
\r
14 of conditions and the following disclaimer in their documentation;
\r
16 3. the name of the copyright holder is not used to endorse products
\r
17 built using this software without specific written permission.
\r
21 This software is provided 'as is' with no explicit or implied warranties
\r
22 in respect of its properties, including, but not limited to, correctness
\r
23 and/or fitness for purpose.
\r
24 ---------------------------------------------------------------------------
\r
25 Issue Date: 20/12/2007
\r
27 These subroutines implement multiple block AES modes for ECB, CBC, CFB,
\r
28 OFB and CTR encryption, The code provides support for the VIA Advanced
\r
29 Cryptography Engine (ACE).
\r
31 NOTE: In the following subroutines, the AES contexts (ctx) must be
\r
32 16 byte aligned if VIA ACE is being used
\r
40 #if defined( AES_MODES )
\r
41 #if defined(__cplusplus)
\r
46 #if defined( _MSC_VER ) && ( _MSC_VER > 800 )
\r
47 #pragma intrinsic(memcpy)
\r
50 #define BFR_BLOCKS 8
\r
52 /* These values are used to detect long word alignment in order to */
\r
53 /* speed up some buffer operations. This facility may not work on */
\r
54 /* some machines so this define can be commented out if necessary */
\r
56 #define FAST_BUFFER_OPERATIONS
\r
58 #define lp32(x) ((uint_32t*)(x))
\r
60 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
62 #include "aes_via_ace.h"
\r
66 aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA;
\r
67 aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA;
\r
68 aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA;
\r
69 aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA;
\r
70 aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA;
\r
71 aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA;
\r
73 /* NOTE: These control word macros must only be used after */
\r
74 /* a key has been set up because they depend on key size */
\r
76 #if NEH_KEY_TYPE == NEH_LOAD
\r
77 #define kd_adr(c) ((uint_8t*)(c)->ks)
\r
78 #elif NEH_KEY_TYPE == NEH_GENERATE
\r
79 #define kd_adr(c) ((uint_8t*)(c)->ks + (c)->inf.b[0])
\r
81 #define kd_adr(c) ((uint_8t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0))
\r
86 #define aligned_array(type, name, no, stride) type name[no]
\r
87 #define aligned_auto(type, name, no, stride) type name[no]
\r
91 #if defined( _MSC_VER ) && _MSC_VER > 1200
\r
93 #define via_cwd(cwd, ty, dir, len) \
\r
94 unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4))
\r
98 #define via_cwd(cwd, ty, dir, len) \
\r
99 aligned_auto(unsigned long, cwd, 4, 16); \
\r
100 cwd[1] = cwd[2] = cwd[3] = 0; \
\r
101 cwd[0] = neh_##dir##_##ty##_key(len)
\r
105 /* test the code for detecting and setting pointer alignment */
\r
107 AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */
\r
109 uint_32t i, count_eq = 0, count_neq = 0;
\r
111 if(n < 4 || n > 16)
\r
112 return EXIT_FAILURE;
\r
114 for(i = 0; i < n; ++i)
\r
116 uint_8t *qf = ALIGN_FLOOR(p + i, n),
\r
117 *qh = ALIGN_CEIL(p + i, n);
\r
121 else if(qh == qf + n)
\r
124 return EXIT_FAILURE;
\r
126 return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS);
\r
129 AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1])
\r
132 return EXIT_SUCCESS;
\r
135 AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
136 int len, const aes_encrypt_ctx ctx[1])
\r
137 { int nb = len >> 4;
\r
139 if(len & (AES_BLOCK_SIZE - 1))
\r
140 return EXIT_FAILURE;
\r
142 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
144 if(ctx->inf.b[1] == 0xff)
\r
145 { uint_8t *ksp = (uint_8t*)(ctx->ks);
\r
146 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
148 if(ALIGN_OFFSET( ctx, 16 ))
\r
149 return EXIT_FAILURE;
\r
151 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
153 via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
\r
156 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
161 int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
\r
163 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
164 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
167 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
169 via_ecb_op5(ksp, cwd, ip, op, m);
\r
172 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
174 ibuf += m * AES_BLOCK_SIZE;
\r
175 obuf += m * AES_BLOCK_SIZE;
\r
180 return EXIT_SUCCESS;
\r
185 #if !defined( ASSUME_VIA_ACE_PRESENT )
\r
188 if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
\r
189 return EXIT_FAILURE;
\r
190 ibuf += AES_BLOCK_SIZE;
\r
191 obuf += AES_BLOCK_SIZE;
\r
194 return EXIT_SUCCESS;
\r
197 AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
198 int len, const aes_decrypt_ctx ctx[1])
\r
199 { int nb = len >> 4;
\r
201 if(len & (AES_BLOCK_SIZE - 1))
\r
202 return EXIT_FAILURE;
\r
204 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
206 if(ctx->inf.b[1] == 0xff)
\r
207 { uint_8t *ksp = kd_adr(ctx);
\r
208 via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
\r
210 if(ALIGN_OFFSET( ctx, 16 ))
\r
211 return EXIT_FAILURE;
\r
213 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
215 via_ecb_op5(ksp, cwd, ibuf, obuf, nb);
\r
218 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
223 int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
\r
225 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
226 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
229 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
231 via_ecb_op5(ksp, cwd, ip, op, m);
\r
234 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
236 ibuf += m * AES_BLOCK_SIZE;
\r
237 obuf += m * AES_BLOCK_SIZE;
\r
242 return EXIT_SUCCESS;
\r
247 #if !defined( ASSUME_VIA_ACE_PRESENT )
\r
250 if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
\r
251 return EXIT_FAILURE;
\r
252 ibuf += AES_BLOCK_SIZE;
\r
253 obuf += AES_BLOCK_SIZE;
\r
256 return EXIT_SUCCESS;
\r
259 AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
260 int len, unsigned char *iv, const aes_encrypt_ctx ctx[1])
\r
261 { int nb = len >> 4;
\r
263 if(len & (AES_BLOCK_SIZE - 1))
\r
264 return EXIT_FAILURE;
\r
266 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
268 if(ctx->inf.b[1] == 0xff)
\r
269 { uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
270 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
271 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
273 if(ALIGN_OFFSET( ctx, 16 ))
\r
274 return EXIT_FAILURE;
\r
276 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
279 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
282 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
\r
284 via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
\r
287 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
292 int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
\r
294 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
295 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
298 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
300 via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp);
\r
303 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
305 ibuf += m * AES_BLOCK_SIZE;
\r
306 obuf += m * AES_BLOCK_SIZE;
\r
312 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
314 return EXIT_SUCCESS;
\r
319 #if !defined( ASSUME_VIA_ACE_PRESENT )
\r
320 # ifdef FAST_BUFFER_OPERATIONS
\r
321 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
324 lp32(iv)[0] ^= lp32(ibuf)[0];
\r
325 lp32(iv)[1] ^= lp32(ibuf)[1];
\r
326 lp32(iv)[2] ^= lp32(ibuf)[2];
\r
327 lp32(iv)[3] ^= lp32(ibuf)[3];
\r
328 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
329 return EXIT_FAILURE;
\r
330 memcpy(obuf, iv, AES_BLOCK_SIZE);
\r
331 ibuf += AES_BLOCK_SIZE;
\r
332 obuf += AES_BLOCK_SIZE;
\r
338 iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1];
\r
339 iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3];
\r
340 iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5];
\r
341 iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7];
\r
342 iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9];
\r
343 iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11];
\r
344 iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13];
\r
345 iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15];
\r
346 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
347 return EXIT_FAILURE;
\r
348 memcpy(obuf, iv, AES_BLOCK_SIZE);
\r
349 ibuf += AES_BLOCK_SIZE;
\r
350 obuf += AES_BLOCK_SIZE;
\r
353 return EXIT_SUCCESS;
\r
356 AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
357 int len, unsigned char *iv, const aes_decrypt_ctx ctx[1])
\r
358 { unsigned char tmp[AES_BLOCK_SIZE];
\r
361 if(len & (AES_BLOCK_SIZE - 1))
\r
362 return EXIT_FAILURE;
\r
364 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
366 if(ctx->inf.b[1] == 0xff)
\r
367 { uint_8t *ksp = kd_adr(ctx), *ivp = iv;
\r
368 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
369 via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
\r
371 if(ALIGN_OFFSET( ctx, 16 ))
\r
372 return EXIT_FAILURE;
\r
374 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
377 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
380 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 ))
\r
382 via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp);
\r
385 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
390 int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb);
\r
392 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
393 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
396 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
398 via_cbc_op6(ksp, cwd, ip, op, m, ivp);
\r
401 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
403 ibuf += m * AES_BLOCK_SIZE;
\r
404 obuf += m * AES_BLOCK_SIZE;
\r
410 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
412 return EXIT_SUCCESS;
\r
416 #if !defined( ASSUME_VIA_ACE_PRESENT )
\r
417 # ifdef FAST_BUFFER_OPERATIONS
\r
418 if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
421 memcpy(tmp, ibuf, AES_BLOCK_SIZE);
\r
422 if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
\r
423 return EXIT_FAILURE;
\r
424 lp32(obuf)[0] ^= lp32(iv)[0];
\r
425 lp32(obuf)[1] ^= lp32(iv)[1];
\r
426 lp32(obuf)[2] ^= lp32(iv)[2];
\r
427 lp32(obuf)[3] ^= lp32(iv)[3];
\r
428 memcpy(iv, tmp, AES_BLOCK_SIZE);
\r
429 ibuf += AES_BLOCK_SIZE;
\r
430 obuf += AES_BLOCK_SIZE;
\r
436 memcpy(tmp, ibuf, AES_BLOCK_SIZE);
\r
437 if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS)
\r
438 return EXIT_FAILURE;
\r
439 obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1];
\r
440 obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3];
\r
441 obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5];
\r
442 obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7];
\r
443 obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9];
\r
444 obuf[10] ^= iv[10]; obuf[11] ^= iv[11];
\r
445 obuf[12] ^= iv[12]; obuf[13] ^= iv[13];
\r
446 obuf[14] ^= iv[14]; obuf[15] ^= iv[15];
\r
447 memcpy(iv, tmp, AES_BLOCK_SIZE);
\r
448 ibuf += AES_BLOCK_SIZE;
\r
449 obuf += AES_BLOCK_SIZE;
\r
452 return EXIT_SUCCESS;
\r
455 AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
456 int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
\r
457 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
\r
459 if(b_pos) /* complete any partial block */
\r
461 while(b_pos < AES_BLOCK_SIZE && cnt < len)
\r
463 *obuf++ = (iv[b_pos++] ^= *ibuf++);
\r
467 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
470 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
472 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
474 if(ctx->inf.b[1] == 0xff)
\r
476 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
477 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
478 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
480 if(ALIGN_OFFSET( ctx, 16 ))
\r
481 return EXIT_FAILURE;
\r
483 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
486 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
489 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
491 via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
\r
492 ibuf += nb * AES_BLOCK_SIZE;
\r
493 obuf += nb * AES_BLOCK_SIZE;
\r
494 cnt += nb * AES_BLOCK_SIZE;
\r
496 else /* input, output or both are unaligned */
\r
497 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
502 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
504 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
505 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
508 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
510 via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
\r
513 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
515 ibuf += m * AES_BLOCK_SIZE;
\r
516 obuf += m * AES_BLOCK_SIZE;
\r
517 cnt += m * AES_BLOCK_SIZE;
\r
522 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
525 # ifdef FAST_BUFFER_OPERATIONS
\r
526 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
527 while(cnt + AES_BLOCK_SIZE <= len)
\r
529 assert(b_pos == 0);
\r
530 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
531 return EXIT_FAILURE;
\r
532 lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
\r
533 lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
\r
534 lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
\r
535 lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
\r
536 ibuf += AES_BLOCK_SIZE;
\r
537 obuf += AES_BLOCK_SIZE;
\r
538 cnt += AES_BLOCK_SIZE;
\r
542 while(cnt + AES_BLOCK_SIZE <= len)
\r
544 assert(b_pos == 0);
\r
545 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
546 return EXIT_FAILURE;
\r
547 obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];
\r
548 obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];
\r
549 obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];
\r
550 obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];
\r
551 obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];
\r
552 obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];
\r
553 obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];
\r
554 obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];
\r
555 ibuf += AES_BLOCK_SIZE;
\r
556 obuf += AES_BLOCK_SIZE;
\r
557 cnt += AES_BLOCK_SIZE;
\r
564 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
565 return EXIT_FAILURE;
\r
567 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
569 *obuf++ = (iv[b_pos++] ^= *ibuf++);
\r
573 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
576 ctx->inf.b[2] = (uint_8t)b_pos;
\r
577 return EXIT_SUCCESS;
\r
580 AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
581 int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
\r
582 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
\r
584 if(b_pos) /* complete any partial block */
\r
587 while(b_pos < AES_BLOCK_SIZE && cnt < len)
\r
590 *obuf++ = t ^ iv[b_pos];
\r
595 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
598 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
600 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
602 if(ctx->inf.b[1] == 0xff)
\r
604 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
605 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
606 via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
\r
608 if(ALIGN_OFFSET( ctx, 16 ))
\r
609 return EXIT_FAILURE;
\r
611 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
614 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
617 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
619 via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
\r
620 ibuf += nb * AES_BLOCK_SIZE;
\r
621 obuf += nb * AES_BLOCK_SIZE;
\r
622 cnt += nb * AES_BLOCK_SIZE;
\r
624 else /* input, output or both are unaligned */
\r
625 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
630 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
632 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
633 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
635 if(ip != ibuf) /* input buffer is not aligned */
\r
636 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
638 via_cfb_op6(ksp, cwd, ip, op, m, ivp);
\r
640 if(op != obuf) /* output buffer is not aligned */
\r
641 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
643 ibuf += m * AES_BLOCK_SIZE;
\r
644 obuf += m * AES_BLOCK_SIZE;
\r
645 cnt += m * AES_BLOCK_SIZE;
\r
650 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
653 # ifdef FAST_BUFFER_OPERATIONS
\r
654 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))
\r
655 while(cnt + AES_BLOCK_SIZE <= len)
\r
658 assert(b_pos == 0);
\r
659 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
660 return EXIT_FAILURE;
\r
661 t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
\r
662 t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
\r
663 t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
\r
664 t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
\r
665 ibuf += AES_BLOCK_SIZE;
\r
666 obuf += AES_BLOCK_SIZE;
\r
667 cnt += AES_BLOCK_SIZE;
\r
671 while(cnt + AES_BLOCK_SIZE <= len)
\r
674 assert(b_pos == 0);
\r
675 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
676 return EXIT_FAILURE;
\r
677 t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;
\r
678 t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;
\r
679 t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;
\r
680 t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;
\r
681 t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;
\r
682 t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;
\r
683 t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;
\r
684 t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;
\r
685 t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;
\r
686 t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;
\r
687 t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
\r
688 t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
\r
689 t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
\r
690 t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
\r
691 t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
\r
692 t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
\r
693 ibuf += AES_BLOCK_SIZE;
\r
694 obuf += AES_BLOCK_SIZE;
\r
695 cnt += AES_BLOCK_SIZE;
\r
703 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
704 return EXIT_FAILURE;
\r
706 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
709 *obuf++ = t ^ iv[b_pos];
\r
714 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
717 ctx->inf.b[2] = (uint_8t)b_pos;
\r
718 return EXIT_SUCCESS;
\r
721 AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
\r
722 int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
\r
723 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
\r
725 if(b_pos) /* complete any partial block */
\r
727 while(b_pos < AES_BLOCK_SIZE && cnt < len)
\r
729 *obuf++ = iv[b_pos++] ^ *ibuf++;
\r
733 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
736 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
738 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
740 if(ctx->inf.b[1] == 0xff)
\r
742 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
743 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
744 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
746 if(ALIGN_OFFSET( ctx, 16 ))
\r
747 return EXIT_FAILURE;
\r
749 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
752 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
755 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
757 via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
\r
758 ibuf += nb * AES_BLOCK_SIZE;
\r
759 obuf += nb * AES_BLOCK_SIZE;
\r
760 cnt += nb * AES_BLOCK_SIZE;
\r
762 else /* input, output or both are unaligned */
\r
763 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
768 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
770 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
771 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
774 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
776 via_ofb_op6(ksp, cwd, ip, op, m, ivp);
\r
779 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
781 ibuf += m * AES_BLOCK_SIZE;
\r
782 obuf += m * AES_BLOCK_SIZE;
\r
783 cnt += m * AES_BLOCK_SIZE;
\r
788 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
791 # ifdef FAST_BUFFER_OPERATIONS
\r
792 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
793 while(cnt + AES_BLOCK_SIZE <= len)
\r
795 assert(b_pos == 0);
\r
796 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
797 return EXIT_FAILURE;
\r
798 lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
\r
799 lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
\r
800 lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
\r
801 lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
\r
802 ibuf += AES_BLOCK_SIZE;
\r
803 obuf += AES_BLOCK_SIZE;
\r
804 cnt += AES_BLOCK_SIZE;
\r
808 while(cnt + AES_BLOCK_SIZE <= len)
\r
810 assert(b_pos == 0);
\r
811 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
812 return EXIT_FAILURE;
\r
813 obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];
\r
814 obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];
\r
815 obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];
\r
816 obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];
\r
817 obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];
\r
818 obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];
\r
819 obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];
\r
820 obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];
\r
821 ibuf += AES_BLOCK_SIZE;
\r
822 obuf += AES_BLOCK_SIZE;
\r
823 cnt += AES_BLOCK_SIZE;
\r
830 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
831 return EXIT_FAILURE;
\r
833 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
835 *obuf++ = iv[b_pos++] ^ *ibuf++;
\r
839 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
842 ctx->inf.b[2] = (uint_8t)b_pos;
\r
843 return EXIT_SUCCESS;
\r
846 #define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
\r
848 AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
\r
849 int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])
\r
850 { unsigned char *ip;
\r
851 int i, blen, b_pos = (int)(ctx->inf.b[2]);
\r
853 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
854 aligned_auto(uint_8t, buf, BFR_LENGTH, 16);
\r
855 if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))
\r
856 return EXIT_FAILURE;
\r
858 uint_8t buf[BFR_LENGTH];
\r
863 memcpy(buf, cbuf, AES_BLOCK_SIZE);
\r
864 if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
\r
865 return EXIT_FAILURE;
\r
867 while(b_pos < AES_BLOCK_SIZE && len)
\r
869 *obuf++ = *ibuf++ ^ buf[b_pos++];
\r
874 ctr_inc(cbuf), b_pos = 0;
\r
879 blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
\r
881 for(i = 0, ip = buf; i < (blen >> 4); ++i)
\r
883 memcpy(ip, cbuf, AES_BLOCK_SIZE);
\r
885 ip += AES_BLOCK_SIZE;
\r
888 if(blen & (AES_BLOCK_SIZE - 1))
\r
889 memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
\r
891 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
892 if(ctx->inf.b[1] == 0xff)
\r
894 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
895 via_ecb_op5((ctx->ks), cwd, buf, buf, i);
\r
899 if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
\r
900 return EXIT_FAILURE;
\r
903 # ifdef FAST_BUFFER_OPERATIONS
\r
904 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))
\r
905 while(i + AES_BLOCK_SIZE <= blen)
\r
907 lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
\r
908 lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
\r
909 lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
\r
910 lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
\r
911 i += AES_BLOCK_SIZE;
\r
912 ip += AES_BLOCK_SIZE;
\r
913 ibuf += AES_BLOCK_SIZE;
\r
914 obuf += AES_BLOCK_SIZE;
\r
918 while(i + AES_BLOCK_SIZE <= blen)
\r
920 obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1];
\r
921 obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3];
\r
922 obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5];
\r
923 obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7];
\r
924 obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9];
\r
925 obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11];
\r
926 obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13];
\r
927 obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15];
\r
928 i += AES_BLOCK_SIZE;
\r
929 ip += AES_BLOCK_SIZE;
\r
930 ibuf += AES_BLOCK_SIZE;
\r
931 obuf += AES_BLOCK_SIZE;
\r
935 *obuf++ = *ibuf++ ^ ip[b_pos++];
\r
938 ctx->inf.b[2] = (uint_8t)b_pos;
\r
939 return EXIT_SUCCESS;
\r
942 #if defined(__cplusplus)
\r