23 #if defined( _MSC_VER ) 24 # define INLINE __inline 25 #elif defined( __GNUC__ ) 26 # define INLINE static inline 28 # error VIA ACE requires Microsoft or GNU C 31 #define NEH_GENERATE 1 35 #define MAX_READ_ATTEMPTS 1000 39 #define NEH_CPU_IS_VIA 0x00000001 40 #define NEH_CPU_READ 0x00000010 41 #define NEH_CPU_MASK 0x00000011 43 #define NEH_RNG_PRESENT 0x00000004 44 #define NEH_RNG_ENABLED 0x00000008 45 #define NEH_ACE_PRESENT 0x00000040 46 #define NEH_ACE_ENABLED 0x00000080 47 #define NEH_RNG_FLAGS (NEH_RNG_PRESENT | NEH_RNG_ENABLED) 48 #define NEH_ACE_FLAGS (NEH_ACE_PRESENT | NEH_ACE_ENABLED) 49 #define NEH_FLAGS_MASK (NEH_RNG_FLAGS | NEH_ACE_FLAGS) 53 #define NEH_GEN_KEY 0x00000000 54 #define NEH_LOAD_KEY 0x00000080 55 #define NEH_ENCRYPT 0x00000000 56 #define NEH_DECRYPT 0x00000200 57 #define NEH_KEY128 0x00000000+0x0a 58 #define NEH_KEY192 0x00000400+0x0c 59 #define NEH_KEY256 0x00000800+0x0e 61 #define NEH_ENC_GEN (NEH_ENCRYPT | NEH_GEN_KEY) 62 #define NEH_DEC_GEN (NEH_DECRYPT | NEH_GEN_KEY) 63 #define NEH_ENC_LOAD (NEH_ENCRYPT | NEH_LOAD_KEY) 64 #define NEH_DEC_LOAD (NEH_DECRYPT | NEH_LOAD_KEY) 66 #define NEH_ENC_GEN_DATA {\ 67 NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\ 68 NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\ 69 NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 } 71 #define NEH_ENC_LOAD_DATA {\ 72 NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\ 73 NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\ 74 NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 } 76 #define NEH_ENC_HYBRID_DATA {\ 77 NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\ 78 NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\ 79 NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 } 81 #define NEH_DEC_GEN_DATA {\ 82 NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\ 83 NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\ 84 NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 } 86 #define NEH_DEC_LOAD_DATA {\ 87 NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\ 88 NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\ 89 NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 } 91 #define NEH_DEC_HYBRID_DATA {\ 92 NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\ 93 NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\ 94 NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 } 96 #define neh_enc_gen_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \ 97 (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256)) 99 #define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) : \ 100 (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256)) 102 #define neh_enc_hybrid_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \ 103 (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256)) 105 #define neh_dec_gen_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \ 106 (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256)) 108 #define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) : \ 109 (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256)) 111 #define neh_dec_hybrid_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \ 112 (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256)) 114 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 ) 115 #define aligned_auto(type, name, no, stride) __declspec(align(stride)) type name[no] 117 #define aligned_auto(type, name, no, stride) \ 118 unsigned char _##name[no * sizeof(type) + stride]; \ 119 type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride)) 122 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 ) 123 #define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no] 124 #elif defined( __GNUC__ ) 125 #define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride))) 127 #define aligned_array(type, name, no, stride) type name[no] 132 static unsigned char via_flags = 0;
134 #if defined ( _MSC_VER ) && ( _MSC_VER > 800 ) 136 #define NEH_REKEY __asm pushfd __asm popfd 137 #define NEH_AES __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7 138 #define NEH_ECB NEH_AES __asm _emit 0xc8 139 #define NEH_CBC NEH_AES __asm _emit 0xd0 140 #define NEH_CFB NEH_AES __asm _emit 0xe0 141 #define NEH_OFB NEH_AES __asm _emit 0xe8 142 #define NEH_RNG __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0 144 INLINE
int has_cpuid(
void)
161 return (
int)ret_value;
164 INLINE
int is_via_cpu(
void)
184 return (
int)ret_value;
187 INLINE
int read_via_flags(
void)
188 {
char ret_value = 0;
197 mov eax,NEH_FLAGS_MASK
203 return (
int)ret_value;
206 INLINE
unsigned int via_rng_in(
void *buf)
207 {
char ret_value = 0x1f;
216 return (
int)ret_value;
219 INLINE
void via_ecb_op5(
220 const void *k,
const void *c,
const void *s,
void *d,
int l)
234 INLINE
void via_cbc_op6(
235 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
250 INLINE
void via_cbc_op7(
251 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
272 INLINE
void via_cfb_op6(
273 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
288 INLINE
void via_cfb_op7(
289 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
310 INLINE
void via_ofb_op6(
311 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
326 #elif defined( __GNUC__ ) 328 #define NEH_REKEY asm("pushfl\n popfl\n\t") 329 #define NEH_ECB asm(".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t") 330 #define NEH_CBC asm(".byte 0xf3, 0x0f, 0xa7, 0xd0\n\t") 331 #define NEH_CFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe0\n\t") 332 #define NEH_OFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe8\n\t") 333 #define NEH_RNG asm(".byte 0x0f, 0xa7, 0xc0\n\t"); 335 INLINE
int has_cpuid(
void)
338 asm(
"movl 0(%esp),%eax\n\t");
339 asm(
"xor $0x00200000,%eax\n\t");
340 asm(
"pushl %eax\n\t");
343 asm(
"popl %eax\n\t");
344 asm(
"xorl 0(%esp),%edx\n\t");
345 asm(
"andl $0x00200000,%eax\n\t");
346 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
351 INLINE
int is_via_cpu(
void)
353 asm(
"pushl %ebx\n\t");
354 asm(
"xorl %eax,%eax\n\t");
356 asm(
"xorl %eax,%eax\n\t");
357 asm(
"subl $0x746e6543,%ebx\n\t");
358 asm(
"orl %ebx,%eax\n\t");
359 asm(
"subl $0x48727561,%edx\n\t");
360 asm(
"orl %edx,%eax\n\t");
361 asm(
"subl $0x736c7561,%ecx\n\t");
362 asm(
"orl %ecx,%eax\n\t");
363 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
364 asm(
"popl %ebx\n\t");
366 via_flags = (val | NEH_CPU_READ);
370 INLINE
int read_via_flags(
void)
372 asm(
"movl $0xc0000000,%eax\n\t");
374 asm(
"movl $0xc0000001,%edx\n\t");
375 asm(
"cmpl %edx,%eax\n\t");
376 asm(
"setae %al\n\t");
377 asm(
"movb %%al,%0\n\t" :
"=m" (val));
379 asm(
"movl $0xc0000001,%eax\n\t");
381 asm(
"movb %%dl,%0\n\t" :
"=m" (val));
382 val &= NEH_FLAGS_MASK;
387 INLINE
int via_rng_in(
void *buf)
389 asm(
"pushl %edi\n\t");
390 asm(
"movl %0,%%edi\n\t" : :
"m" (buf));
391 asm(
"xorl %edx,%edx\n\t");
393 asm(
"andl $0x0000001f,%eax\n\t");
394 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
395 asm(
"popl %edi\n\t");
399 INLINE
volatile void via_ecb_op5(
400 const void *k,
const void *c,
const void *s,
void *d,
int l)
402 asm(
"pushl %ebx\n\t");
404 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
405 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
406 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
407 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
408 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
410 asm(
"popl %ebx\n\t");
413 INLINE
volatile void via_cbc_op6(
414 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
416 asm(
"pushl %ebx\n\t");
418 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
419 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
420 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
421 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
422 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
423 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
425 asm(
"popl %ebx\n\t");
428 INLINE
volatile void via_cbc_op7(
429 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
431 asm(
"pushl %ebx\n\t");
433 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
434 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
435 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
436 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
437 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
438 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
440 asm(
"movl %eax,%esi\n\t");
441 asm(
"movl %0, %%edi\n\t" : :
"m" (w));
442 asm(
"movsl; movsl; movsl; movsl\n\t");
443 asm(
"popl %ebx\n\t");
446 INLINE
volatile void via_cfb_op6(
447 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
449 asm(
"pushl %ebx\n\t");
451 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
452 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
453 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
454 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
455 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
456 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
458 asm(
"popl %ebx\n\t");
461 INLINE
volatile void via_cfb_op7(
462 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
464 asm(
"pushl %ebx\n\t");
466 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
467 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
468 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
469 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
470 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
471 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
473 asm(
"movl %eax,%esi\n\t");
474 asm(
"movl %0, %%edi\n\t" : :
"m" (w));
475 asm(
"movsl; movsl; movsl; movsl\n\t");
476 asm(
"popl %ebx\n\t");
479 INLINE
volatile void via_ofb_op6(
480 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
482 asm(
"pushl %ebx\n\t");
484 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
485 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
486 asm(
"movl %0, %%esi\n\t" : :
"m" (s));
487 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
488 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
489 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
491 asm(
"popl %ebx\n\t");
495 #error VIA ACE is not available with this compiler 498 INLINE
int via_ace_test(
void)
500 return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_ACE_FLAGS) == NEH_ACE_FLAGS);
503 #define VIA_ACE_AVAILABLE (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS) \ 504 || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test()) 506 INLINE
int via_rng_test(
void)
508 return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_RNG_FLAGS) == NEH_RNG_FLAGS);
511 #define VIA_RNG_AVAILABLE (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS) \ 512 || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test()) 514 INLINE
int read_via_rng(
void *buf,
int count)
515 {
int nbr, max_reads, lcnt = count;
516 unsigned char *p, *q;
517 aligned_auto(
unsigned char, bp, 64, 16);
519 if(!VIA_RNG_AVAILABLE)
524 max_reads = MAX_READ_ATTEMPTS;
526 nbr = via_rng_in(bp);
528 (nbr == 0 && --max_reads);
531 p = (
unsigned char*)buf; q = bp;