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
462 *obuf++ = iv[b_pos++] ^= *ibuf++, cnt++;
\r
464 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
467 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
469 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
471 if(ctx->inf.b[1] == 0xff)
\r
473 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
474 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
475 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
477 if(ALIGN_OFFSET( ctx, 16 ))
\r
478 return EXIT_FAILURE;
\r
480 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
483 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
486 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
488 via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp);
\r
489 ibuf += nb * AES_BLOCK_SIZE;
\r
490 obuf += nb * AES_BLOCK_SIZE;
\r
491 cnt += nb * AES_BLOCK_SIZE;
\r
493 else /* input, output or both are unaligned */
\r
494 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
499 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
501 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
502 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
505 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
507 via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp);
\r
510 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
512 ibuf += m * AES_BLOCK_SIZE;
\r
513 obuf += m * AES_BLOCK_SIZE;
\r
514 cnt += m * AES_BLOCK_SIZE;
\r
519 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
522 # ifdef FAST_BUFFER_OPERATIONS
\r
523 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
524 while(cnt + AES_BLOCK_SIZE <= len)
\r
526 assert(b_pos == 0);
\r
527 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
528 return EXIT_FAILURE;
\r
529 lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0];
\r
530 lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1];
\r
531 lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2];
\r
532 lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3];
\r
533 ibuf += AES_BLOCK_SIZE;
\r
534 obuf += AES_BLOCK_SIZE;
\r
535 cnt += AES_BLOCK_SIZE;
\r
539 while(cnt + AES_BLOCK_SIZE <= len)
\r
541 assert(b_pos == 0);
\r
542 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
543 return EXIT_FAILURE;
\r
544 obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1];
\r
545 obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3];
\r
546 obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5];
\r
547 obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7];
\r
548 obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9];
\r
549 obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11];
\r
550 obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13];
\r
551 obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15];
\r
552 ibuf += AES_BLOCK_SIZE;
\r
553 obuf += AES_BLOCK_SIZE;
\r
554 cnt += AES_BLOCK_SIZE;
\r
561 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
562 return EXIT_FAILURE;
\r
564 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
565 *obuf++ = iv[b_pos++] ^= *ibuf++, cnt++;
\r
567 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
570 ctx->inf.b[2] = b_pos;
\r
571 return EXIT_SUCCESS;
\r
574 AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf,
\r
575 int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
\r
576 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
\r
578 if(b_pos) /* complete any partial block */
\r
581 while(b_pos < AES_BLOCK_SIZE && cnt < len)
\r
582 t = *ibuf++, *obuf++ = t ^ iv[b_pos], iv[b_pos++] = t, cnt++;
\r
584 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
587 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
589 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
591 if(ctx->inf.b[1] == 0xff)
\r
593 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
594 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
595 via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192);
\r
597 if(ALIGN_OFFSET( ctx, 16 ))
\r
598 return EXIT_FAILURE;
\r
600 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
603 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
606 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
608 via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
\r
609 ibuf += nb * AES_BLOCK_SIZE;
\r
610 obuf += nb * AES_BLOCK_SIZE;
\r
611 cnt += nb * AES_BLOCK_SIZE;
\r
613 else /* input, output or both are unaligned */
\r
614 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
619 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
621 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
622 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
624 if(ip != ibuf) /* input buffer is not aligned */
\r
625 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
627 via_cfb_op6(ksp, cwd, ip, op, m, ivp);
\r
629 if(op != obuf) /* output buffer is not aligned */
\r
630 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
632 ibuf += m * AES_BLOCK_SIZE;
\r
633 obuf += m * AES_BLOCK_SIZE;
\r
634 cnt += m * AES_BLOCK_SIZE;
\r
639 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
642 # ifdef FAST_BUFFER_OPERATIONS
\r
643 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 ))
\r
644 while(cnt + AES_BLOCK_SIZE <= len)
\r
647 assert(b_pos == 0);
\r
648 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
649 return EXIT_FAILURE;
\r
650 t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t;
\r
651 t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t;
\r
652 t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t;
\r
653 t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t;
\r
654 ibuf += AES_BLOCK_SIZE;
\r
655 obuf += AES_BLOCK_SIZE;
\r
656 cnt += AES_BLOCK_SIZE;
\r
660 while(cnt + AES_BLOCK_SIZE <= len)
\r
663 assert(b_pos == 0);
\r
664 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
665 return EXIT_FAILURE;
\r
666 t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t;
\r
667 t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t;
\r
668 t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t;
\r
669 t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t;
\r
670 t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t;
\r
671 t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t;
\r
672 t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t;
\r
673 t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t;
\r
674 t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t;
\r
675 t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t;
\r
676 t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t;
\r
677 t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t;
\r
678 t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t;
\r
679 t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t;
\r
680 t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t;
\r
681 t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t;
\r
682 ibuf += AES_BLOCK_SIZE;
\r
683 obuf += AES_BLOCK_SIZE;
\r
684 cnt += AES_BLOCK_SIZE;
\r
692 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
693 return EXIT_FAILURE;
\r
695 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
696 t = *ibuf++, *obuf++ = t ^ iv[b_pos], iv[b_pos++] = t, cnt++;
\r
698 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
701 ctx->inf.b[2] = b_pos;
\r
702 return EXIT_SUCCESS;
\r
705 AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf,
\r
706 int len, unsigned char *iv, aes_encrypt_ctx ctx[1])
\r
707 { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb;
\r
709 if(b_pos) /* complete any partial block */
\r
711 while(b_pos < AES_BLOCK_SIZE && cnt < len)
\r
712 *obuf++ = iv[b_pos++] ^ *ibuf++, cnt++;
\r
714 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
717 if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */
\r
719 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
721 if(ctx->inf.b[1] == 0xff)
\r
723 uint_8t *ksp = (uint_8t*)(ctx->ks), *ivp = iv;
\r
724 aligned_auto(uint_8t, liv, AES_BLOCK_SIZE, 16);
\r
725 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
727 if(ALIGN_OFFSET( ctx, 16 ))
\r
728 return EXIT_FAILURE;
\r
730 if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */
\r
733 memcpy(liv, iv, AES_BLOCK_SIZE);
\r
736 if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ))
\r
738 via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp);
\r
739 ibuf += nb * AES_BLOCK_SIZE;
\r
740 obuf += nb * AES_BLOCK_SIZE;
\r
741 cnt += nb * AES_BLOCK_SIZE;
\r
743 else /* input, output or both are unaligned */
\r
744 { aligned_auto(uint_8t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16);
\r
749 m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m;
\r
751 ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf);
\r
752 op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf);
\r
755 memcpy(buf, ibuf, m * AES_BLOCK_SIZE);
\r
757 via_ofb_op6(ksp, cwd, ip, op, m, ivp);
\r
760 memcpy(obuf, buf, m * AES_BLOCK_SIZE);
\r
762 ibuf += m * AES_BLOCK_SIZE;
\r
763 obuf += m * AES_BLOCK_SIZE;
\r
764 cnt += m * AES_BLOCK_SIZE;
\r
769 memcpy(iv, ivp, AES_BLOCK_SIZE);
\r
772 # ifdef FAST_BUFFER_OPERATIONS
\r
773 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 ))
\r
774 while(cnt + AES_BLOCK_SIZE <= len)
\r
776 assert(b_pos == 0);
\r
777 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
778 return EXIT_FAILURE;
\r
779 lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0];
\r
780 lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1];
\r
781 lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2];
\r
782 lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3];
\r
783 ibuf += AES_BLOCK_SIZE;
\r
784 obuf += AES_BLOCK_SIZE;
\r
785 cnt += AES_BLOCK_SIZE;
\r
789 while(cnt + AES_BLOCK_SIZE <= len)
\r
791 assert(b_pos == 0);
\r
792 if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
793 return EXIT_FAILURE;
\r
794 obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1];
\r
795 obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3];
\r
796 obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5];
\r
797 obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7];
\r
798 obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9];
\r
799 obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11];
\r
800 obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13];
\r
801 obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15];
\r
802 ibuf += AES_BLOCK_SIZE;
\r
803 obuf += AES_BLOCK_SIZE;
\r
804 cnt += AES_BLOCK_SIZE;
\r
811 if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
\r
812 return EXIT_FAILURE;
\r
814 while(cnt < len && b_pos < AES_BLOCK_SIZE)
\r
815 *obuf++ = iv[b_pos++] ^ *ibuf++, cnt++;
\r
817 b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos);
\r
820 ctx->inf.b[2] = b_pos;
\r
821 return EXIT_SUCCESS;
\r
824 #define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE)
\r
826 AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf,
\r
827 int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1])
\r
829 int i, blen, b_pos = (int)(ctx->inf.b[2]);
\r
831 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
832 aligned_auto(uint_8t, buf, BFR_LENGTH, 16);
\r
833 if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 ))
\r
834 return EXIT_FAILURE;
\r
836 uint_8t buf[BFR_LENGTH];
\r
841 memcpy(buf, cbuf, AES_BLOCK_SIZE);
\r
842 if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
\r
843 return EXIT_FAILURE;
\r
844 while(b_pos < AES_BLOCK_SIZE && len)
\r
845 *obuf++ = *ibuf++ ^ buf[b_pos++], --len;
\r
847 ctr_inc(cbuf), b_pos = 0;
\r
852 blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen;
\r
854 for(i = 0, ip = buf; i < (blen >> 4); ++i)
\r
856 memcpy(ip, cbuf, AES_BLOCK_SIZE);
\r
858 ip += AES_BLOCK_SIZE;
\r
861 if(blen & (AES_BLOCK_SIZE - 1))
\r
862 memcpy(ip, cbuf, AES_BLOCK_SIZE), i++;
\r
864 #if defined( USE_VIA_ACE_IF_PRESENT )
\r
865 if(ctx->inf.b[1] == 0xff)
\r
867 via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192);
\r
868 via_ecb_op5((ctx->ks),cwd,buf,buf,i);
\r
872 if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS)
\r
873 return EXIT_FAILURE;
\r
876 # ifdef FAST_BUFFER_OPERATIONS
\r
877 if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 ))
\r
878 while(i + AES_BLOCK_SIZE <= blen)
\r
880 lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0];
\r
881 lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1];
\r
882 lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2];
\r
883 lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3];
\r
884 i += AES_BLOCK_SIZE;
\r
885 ip += AES_BLOCK_SIZE;
\r
886 ibuf += AES_BLOCK_SIZE;
\r
887 obuf += AES_BLOCK_SIZE;
\r
891 while(i + AES_BLOCK_SIZE <= blen)
\r
893 obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1];
\r
894 obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3];
\r
895 obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5];
\r
896 obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7];
\r
897 obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9];
\r
898 obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11];
\r
899 obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13];
\r
900 obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15];
\r
901 i += AES_BLOCK_SIZE;
\r
902 ip += AES_BLOCK_SIZE;
\r
903 ibuf += AES_BLOCK_SIZE;
\r
904 obuf += AES_BLOCK_SIZE;
\r
908 *obuf++ = *ibuf++ ^ ip[b_pos++];
\r
911 ctx->inf.b[2] = b_pos;
\r
912 return EXIT_SUCCESS;
\r
915 #if defined(__cplusplus)
\r