36 #if defined( _MSC_VER )
37 # define INLINE __inline
38 #elif defined( __GNUC__ )
39 # define INLINE static inline
41 # error VIA ACE requires Microsoft or GNU C
44 #define NEH_GENERATE 1
48 #define MAX_READ_ATTEMPTS 1000
52 #define NEH_CPU_IS_VIA 0x00000001
53 #define NEH_CPU_READ 0x00000010
54 #define NEH_CPU_MASK 0x00000011
56 #define NEH_RNG_PRESENT 0x00000004
57 #define NEH_RNG_ENABLED 0x00000008
58 #define NEH_ACE_PRESENT 0x00000040
59 #define NEH_ACE_ENABLED 0x00000080
60 #define NEH_RNG_FLAGS (NEH_RNG_PRESENT | NEH_RNG_ENABLED)
61 #define NEH_ACE_FLAGS (NEH_ACE_PRESENT | NEH_ACE_ENABLED)
62 #define NEH_FLAGS_MASK (NEH_RNG_FLAGS | NEH_ACE_FLAGS)
66 #define NEH_GEN_KEY 0x00000000
67 #define NEH_LOAD_KEY 0x00000080
68 #define NEH_ENCRYPT 0x00000000
69 #define NEH_DECRYPT 0x00000200
70 #define NEH_KEY128 0x00000000+0x0a
71 #define NEH_KEY192 0x00000400+0x0c
72 #define NEH_KEY256 0x00000800+0x0e
74 #define NEH_ENC_GEN (NEH_ENCRYPT | NEH_GEN_KEY)
75 #define NEH_DEC_GEN (NEH_DECRYPT | NEH_GEN_KEY)
76 #define NEH_ENC_LOAD (NEH_ENCRYPT | NEH_LOAD_KEY)
77 #define NEH_DEC_LOAD (NEH_DECRYPT | NEH_LOAD_KEY)
79 #define NEH_ENC_GEN_DATA {\
80 NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\
81 NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\
82 NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 }
84 #define NEH_ENC_LOAD_DATA {\
85 NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\
86 NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\
87 NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }
89 #define NEH_ENC_HYBRID_DATA {\
90 NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\
91 NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\
92 NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }
94 #define NEH_DEC_GEN_DATA {\
95 NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\
96 NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\
97 NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 }
99 #define NEH_DEC_LOAD_DATA {\
100 NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\
101 NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\
102 NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }
104 #define NEH_DEC_HYBRID_DATA {\
105 NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\
106 NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\
107 NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }
109 #define neh_enc_gen_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \
110 (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256))
112 #define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) : \
113 (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))
115 #define neh_enc_hybrid_key(x) ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) : \
116 (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))
118 #define neh_dec_gen_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \
119 (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256))
121 #define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) : \
122 (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))
124 #define neh_dec_hybrid_key(x) ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) : \
125 (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))
127 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 )
128 #define aligned_auto(type, name, no, stride) __declspec(align(stride)) type name[no]
130 #define aligned_auto(type, name, no, stride) \
131 unsigned char _##name[no * sizeof(type) + stride]; \
132 type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride))
135 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 )
136 #define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no]
137 #elif defined( __GNUC__ )
138 #define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride)))
140 #define aligned_array(type, name, no, stride) type name[no]
145 static unsigned char via_flags = 0;
147 #if defined ( _MSC_VER ) && ( _MSC_VER > 800 )
149 #define NEH_REKEY __asm pushfd __asm popfd
150 #define NEH_AES __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7
151 #define NEH_ECB NEH_AES __asm _emit 0xc8
152 #define NEH_CBC NEH_AES __asm _emit 0xd0
153 #define NEH_CFB NEH_AES __asm _emit 0xe0
154 #define NEH_OFB NEH_AES __asm _emit 0xe8
155 #define NEH_RNG __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0
157 INLINE
int has_cpuid(
void)
174 return (
int)ret_value;
177 INLINE
int is_via_cpu(
void)
195 return (
int)ret_value;
198 INLINE
int read_via_flags(
void)
199 {
char ret_value = 0;
215 return (
int)ret_value;
218 INLINE
unsigned int via_rng_in(
void *buf)
219 {
char ret_value = 0x1f;
229 return (
int)ret_value;
232 INLINE
volatile void via_ecb_op5(
233 const void *k,
const void *c,
const void *
s,
void *d,
int l)
246 INLINE
volatile void via_cbc_op6(
247 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
261 INLINE
volatile void via_cbc_op7(
262 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
282 INLINE
volatile void via_cfb_op6(
283 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
297 INLINE
volatile void via_cfb_op7(
298 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
318 INLINE
volatile void via_ofb_op6(
319 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
333 #elif defined( __GNUC__ )
335 #define NEH_REKEY asm("pushfl\n popfl\n\t")
336 #define NEH_ECB asm(".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t")
337 #define NEH_CBC asm(".byte 0xf3, 0x0f, 0xa7, 0xd0\n\t")
338 #define NEH_CFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe0\n\t")
339 #define NEH_OFB asm(".byte 0xf3, 0x0f, 0xa7, 0xe8\n\t")
340 #define NEH_RNG asm(".byte 0x0f, 0xa7, 0xc0\n\t");
342 INLINE
int has_cpuid(
void)
345 asm(
"movl 0(%esp),%eax\n\t");
346 asm(
"xor $0x00200000,%eax\n\t");
347 asm(
"pushl %eax\n\t");
350 asm(
"popl %eax\n\t");
351 asm(
"xorl 0(%esp),%edx\n\t");
352 asm(
"andl $0x00200000,%eax\n\t");
353 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
358 INLINE
int is_via_cpu(
void)
360 asm(
"xorl %eax,%eax\n\t");
362 asm(
"xorl %eax,%eax\n\t");
363 asm(
"subl $0x746e6543,%ebx\n\t");
364 asm(
"orl %ebx,%eax\n\t");
365 asm(
"subl $0x48727561,%edx\n\t");
366 asm(
"orl %edx,%eax\n\t");
367 asm(
"subl $0x736c7561,%ecx\n\t");
368 asm(
"orl %ecx,%eax\n\t");
369 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
375 INLINE
int read_via_flags(
void)
377 asm(
"movl $0xc0000000,%eax\n\t");
379 asm(
"movl $0xc0000001,%edx\n\t");
380 asm(
"cmpl %edx,%eax\n\t");
381 asm(
"setae %al\n\t");
382 asm(
"movb %%al,%0\n\t" :
"=m" (val));
384 asm(
"movl $0xc0000001,%eax\n\t");
386 asm(
"movb %%dl,%0\n\t" :
"=m" (val));
392 INLINE
int via_rng_in(
void *buf)
394 asm(
"pushl %edi\n\t");
395 asm(
"movl %0,%%edi\n\t" : :
"m" (buf));
396 asm(
"xorl %edx,%edx\n\t");
398 asm(
"andl $0x0000001f,%eax\n\t");
399 asm(
"movl %%eax,%0\n\t" :
"=m" (val));
400 asm(
"popl %edi\n\t");
404 INLINE
volatile void via_ecb_op5(
405 const void *k,
const void *c,
const void *s,
void *d,
int l)
408 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
409 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
410 asm(
"movl %0, %%esi\n\t" : :
"m" (
s));
411 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
412 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
416 INLINE
volatile void via_cbc_op6(
417 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
420 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
421 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
422 asm(
"movl %0, %%esi\n\t" : :
"m" (
s));
423 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
424 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
425 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
429 INLINE
volatile void via_cbc_op7(
430 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
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");
445 INLINE
volatile void via_cfb_op6(
446 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
449 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
450 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
451 asm(
"movl %0, %%esi\n\t" : :
"m" (
s));
452 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
453 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
454 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
458 INLINE
volatile void via_cfb_op7(
459 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v,
void *w)
462 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
463 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
464 asm(
"movl %0, %%esi\n\t" : :
"m" (
s));
465 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
466 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
467 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
469 asm(
"movl %eax,%esi\n\t");
470 asm(
"movl %0, %%edi\n\t" : :
"m" (w));
471 asm(
"movsl; movsl; movsl; movsl\n\t");
474 INLINE
volatile void via_ofb_op6(
475 const void *k,
const void *c,
const void *s,
void *d,
int l,
void *v)
478 asm(
"movl %0, %%ebx\n\t" : :
"m" (k));
479 asm(
"movl %0, %%edx\n\t" : :
"m" (c));
480 asm(
"movl %0, %%esi\n\t" : :
"m" (
s));
481 asm(
"movl %0, %%edi\n\t" : :
"m" (d));
482 asm(
"movl %0, %%ecx\n\t" : :
"m" (l));
483 asm(
"movl %0, %%eax\n\t" : :
"m" (v));
488 #error VIA ACE is not available with this compiler
496 #define VIA_ACE_AVAILABLE (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS) \
497 || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test())
504 #define VIA_RNG_AVAILABLE (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS) \
505 || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test())
508 {
int nbr, max_reads, lcnt = count;
509 unsigned char *
p, *q;
519 nbr = via_rng_in(bp);
521 (nbr == 0 && --max_reads);
524 p = (
unsigned char*)buf; q = bp;