OSDN Git Service

Change behavior of quick connect.
[ffftp/ffftp.git] / aes_via_ace.h
1 /*\r
2  ---------------------------------------------------------------------------\r
3  Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.\r
4 \r
5  LICENSE TERMS\r
6 \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
9 \r
10   1. source code distributions include the above copyright notice, this\r
11      list of conditions and the following disclaimer;\r
12 \r
13   2. binary distributions include the above copyright notice, this list\r
14      of conditions and the following disclaimer in their documentation;\r
15 \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
18 \r
19  DISCLAIMER\r
20 \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/20077\r
26 */\r
27 \r
28 #ifndef AES_VIA_ACE_H\r
29 #define AES_VIA_ACE_H\r
30 \r
31 #if defined( _MSC_VER )\r
32 #  define INLINE  __inline\r
33 #elif defined( __GNUC__ )\r
34 #  define INLINE  static inline\r
35 #else\r
36 #  error VIA ACE requires Microsoft or GNU C\r
37 #endif\r
38 \r
39 #define NEH_GENERATE    1\r
40 #define NEH_LOAD        2\r
41 #define NEH_HYBRID      3\r
42 \r
43 #define MAX_READ_ATTEMPTS   1000\r
44 \r
45 /* VIA Nehemiah RNG and ACE Feature Mask Values */\r
46 \r
47 #define NEH_CPU_IS_VIA      0x00000001\r
48 #define NEH_CPU_READ        0x00000010\r
49 #define NEH_CPU_MASK        0x00000011\r
50 \r
51 #define NEH_RNG_PRESENT     0x00000004\r
52 #define NEH_RNG_ENABLED     0x00000008\r
53 #define NEH_ACE_PRESENT     0x00000040\r
54 #define NEH_ACE_ENABLED     0x00000080\r
55 #define NEH_RNG_FLAGS       (NEH_RNG_PRESENT | NEH_RNG_ENABLED)\r
56 #define NEH_ACE_FLAGS       (NEH_ACE_PRESENT | NEH_ACE_ENABLED)\r
57 #define NEH_FLAGS_MASK      (NEH_RNG_FLAGS | NEH_ACE_FLAGS)\r
58 \r
59 /* VIA Nehemiah Advanced Cryptography Engine (ACE) Control Word Values  */\r
60 \r
61 #define NEH_GEN_KEY     0x00000000      /* generate key schedule        */\r
62 #define NEH_LOAD_KEY    0x00000080      /* load schedule from memory    */\r
63 #define NEH_ENCRYPT     0x00000000      /* encryption                   */\r
64 #define NEH_DECRYPT     0x00000200      /* decryption                   */\r
65 #define NEH_KEY128      0x00000000+0x0a /* 128 bit key                  */\r
66 #define NEH_KEY192      0x00000400+0x0c /* 192 bit key                  */\r
67 #define NEH_KEY256      0x00000800+0x0e /* 256 bit key                  */\r
68 \r
69 #define NEH_ENC_GEN     (NEH_ENCRYPT | NEH_GEN_KEY)\r
70 #define NEH_DEC_GEN     (NEH_DECRYPT | NEH_GEN_KEY)\r
71 #define NEH_ENC_LOAD    (NEH_ENCRYPT | NEH_LOAD_KEY)\r
72 #define NEH_DEC_LOAD    (NEH_DECRYPT | NEH_LOAD_KEY)\r
73 \r
74 #define NEH_ENC_GEN_DATA {\\r
75     NEH_ENC_GEN | NEH_KEY128, 0, 0, 0,\\r
76     NEH_ENC_GEN | NEH_KEY192, 0, 0, 0,\\r
77     NEH_ENC_GEN | NEH_KEY256, 0, 0, 0 }\r
78 \r
79 #define NEH_ENC_LOAD_DATA {\\r
80     NEH_ENC_LOAD | NEH_KEY128, 0, 0, 0,\\r
81     NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\\r
82     NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }\r
83 \r
84 #define NEH_ENC_HYBRID_DATA {\\r
85     NEH_ENC_GEN  | NEH_KEY128, 0, 0, 0,\\r
86     NEH_ENC_LOAD | NEH_KEY192, 0, 0, 0,\\r
87     NEH_ENC_LOAD | NEH_KEY256, 0, 0, 0 }\r
88 \r
89 #define NEH_DEC_GEN_DATA {\\r
90     NEH_DEC_GEN | NEH_KEY128, 0, 0, 0,\\r
91     NEH_DEC_GEN | NEH_KEY192, 0, 0, 0,\\r
92     NEH_DEC_GEN | NEH_KEY256, 0, 0, 0 }\r
93 \r
94 #define NEH_DEC_LOAD_DATA {\\r
95     NEH_DEC_LOAD | NEH_KEY128, 0, 0, 0,\\r
96     NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\\r
97     NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }\r
98 \r
99 #define NEH_DEC_HYBRID_DATA {\\r
100     NEH_DEC_GEN  | NEH_KEY128, 0, 0, 0,\\r
101     NEH_DEC_LOAD | NEH_KEY192, 0, 0, 0,\\r
102     NEH_DEC_LOAD | NEH_KEY256, 0, 0, 0 }\r
103 \r
104 #define neh_enc_gen_key(x)  ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :      \\r
105      (x) == 192 ? (NEH_ENC_GEN | NEH_KEY192) : (NEH_ENC_GEN | NEH_KEY256))\r
106 \r
107 #define neh_enc_load_key(x) ((x) == 128 ? (NEH_ENC_LOAD | NEH_KEY128) :     \\r
108      (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))\r
109 \r
110 #define neh_enc_hybrid_key(x)   ((x) == 128 ? (NEH_ENC_GEN | NEH_KEY128) :  \\r
111      (x) == 192 ? (NEH_ENC_LOAD | NEH_KEY192) : (NEH_ENC_LOAD | NEH_KEY256))\r
112 \r
113 #define neh_dec_gen_key(x)  ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :      \\r
114      (x) == 192 ? (NEH_DEC_GEN | NEH_KEY192) : (NEH_DEC_GEN | NEH_KEY256))\r
115 \r
116 #define neh_dec_load_key(x) ((x) == 128 ? (NEH_DEC_LOAD | NEH_KEY128) :     \\r
117      (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))\r
118 \r
119 #define neh_dec_hybrid_key(x)   ((x) == 128 ? (NEH_DEC_GEN | NEH_KEY128) :  \\r
120      (x) == 192 ? (NEH_DEC_LOAD | NEH_KEY192) : (NEH_DEC_LOAD | NEH_KEY256))\r
121 \r
122 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 )\r
123 #define aligned_auto(type, name, no, stride)  __declspec(align(stride)) type name[no]\r
124 #else\r
125 #define aligned_auto(type, name, no, stride)                \\r
126     unsigned char _##name[no * sizeof(type) + stride];      \\r
127     type *name = (type*)(16 * ((((unsigned long)(_##name)) + stride - 1) / stride))\r
128 #endif\r
129 \r
130 #if defined( _MSC_VER ) && ( _MSC_VER > 1200 )\r
131 #define aligned_array(type, name, no, stride) __declspec(align(stride)) type name[no]\r
132 #elif defined( __GNUC__ )\r
133 #define aligned_array(type, name, no, stride) type name[no] __attribute__ ((aligned(stride)))\r
134 #else\r
135 #define aligned_array(type, name, no, stride) type name[no]\r
136 #endif\r
137 \r
138 /* VIA ACE codeword     */\r
139 \r
140 static unsigned char via_flags = 0;\r
141 \r
142 #if defined ( _MSC_VER ) && ( _MSC_VER > 800 )\r
143 \r
144 #define NEH_REKEY   __asm pushfd __asm popfd\r
145 #define NEH_AES     __asm _emit 0xf3 __asm _emit 0x0f __asm _emit 0xa7\r
146 #define NEH_ECB     NEH_AES __asm _emit 0xc8\r
147 #define NEH_CBC     NEH_AES __asm _emit 0xd0\r
148 #define NEH_CFB     NEH_AES __asm _emit 0xe0\r
149 #define NEH_OFB     NEH_AES __asm _emit 0xe8\r
150 #define NEH_RNG     __asm _emit 0x0f __asm _emit 0xa7 __asm _emit 0xc0\r
151 \r
152 INLINE int has_cpuid(void)\r
153 {   char ret_value;\r
154     __asm\r
155     {   pushfd                  /* save EFLAGS register     */\r
156         mov     eax,[esp]       /* copy it to eax           */\r
157         mov     edx,0x00200000  /* CPUID bit position       */\r
158         xor     eax,edx         /* toggle the CPUID bit     */\r
159         push    eax             /* attempt to set EFLAGS to */\r
160         popfd                   /*     the new value        */\r
161         pushfd                  /* get the new EFLAGS value */\r
162         pop     eax             /*     into eax             */\r
163         xor     eax,[esp]       /* xor with original value  */\r
164         and     eax,edx         /* has CPUID bit changed?   */\r
165         setne   al              /* set to 1 if we have been */\r
166         mov     ret_value,al    /*     able to change it    */\r
167         popfd                   /* restore original EFLAGS  */\r
168     }\r
169     return (int)ret_value;\r
170 }\r
171 \r
172 INLINE int is_via_cpu(void)\r
173 {   char ret_value;\r
174     __asm\r
175     {   xor     eax,eax         /* use CPUID to get vendor  */\r
176         cpuid                   /* identity string          */\r
177         xor     eax,eax         /* is it "CentaurHauls" ?   */\r
178         sub     ebx,0x746e6543  /* 'Cent'                   */\r
179         or      eax,ebx\r
180         sub     edx,0x48727561  /* 'aurH'                   */\r
181         or      eax,edx\r
182         sub     ecx,0x736c7561  /* 'auls'                   */\r
183         or      eax,ecx\r
184         sete    al              /* set to 1 if it is VIA ID */\r
185         mov     dl,NEH_CPU_READ /* mark CPU type as read    */\r
186         or      dl,al           /* & store result in flags  */\r
187         mov     [via_flags],dl  /* set VIA detected flag    */\r
188         mov     ret_value,al    /*     able to change it    */\r
189     }\r
190     return (int)ret_value;\r
191 }\r
192 \r
193 INLINE int read_via_flags(void)\r
194 {   char ret_value = 0;\r
195     __asm\r
196     {\r
197         mov     eax,0xC0000000  /* Centaur extended CPUID   */\r
198         cpuid\r
199         mov     edx,0xc0000001  /* >= 0xc0000001 if support */\r
200         cmp     eax,edx         /* for VIA extended feature */\r
201         jnae    no_rng          /*     flags is available   */\r
202         mov     eax,edx         /* read Centaur extended    */\r
203         cpuid                   /*     feature flags        */\r
204         mov     eax,NEH_FLAGS_MASK  /* mask out and save    */\r
205         and     eax,edx         /*  the RNG and ACE flags   */\r
206         or      [via_flags],al  /* present & enabled flags  */\r
207         mov     ret_value,al    /*     able to change it    */\r
208 no_rng:\r
209     }\r
210     return (int)ret_value;\r
211 }\r
212 \r
213 INLINE unsigned int via_rng_in(void *buf)\r
214 {   char ret_value = 0x1f;\r
215     __asm\r
216     {\r
217         push    edi\r
218         mov     edi,buf         /* input buffer address     */\r
219         xor     edx,edx         /* try to fetch 8 bytes     */\r
220         NEH_RNG                 /* do RNG read operation    */\r
221         and     ret_value,al    /* count of bytes returned  */\r
222         pop     edi\r
223     }\r
224     return (int)ret_value;\r
225 }\r
226 \r
227 INLINE void via_ecb_op5(\r
228             const void *k, const void *c, const void *s, void *d, int l)\r
229 {   __asm\r
230     {\r
231         NEH_REKEY\r
232         mov     ebx, (k)\r
233         mov     edx, (c)\r
234         mov     esi, (s)\r
235         mov     edi, (d)\r
236         mov     ecx, (l)\r
237         NEH_ECB\r
238     }\r
239 }\r
240 \r
241 INLINE void via_cbc_op6(\r
242             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
243 {   __asm\r
244     {\r
245         NEH_REKEY\r
246         mov     ebx, (k)\r
247         mov     edx, (c)\r
248         mov     esi, (s)\r
249         mov     edi, (d)\r
250         mov     ecx, (l)\r
251         mov     eax, (v)\r
252         NEH_CBC\r
253     }\r
254 }\r
255 \r
256 INLINE void via_cbc_op7(\r
257         const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\r
258 {   __asm\r
259     {\r
260         NEH_REKEY\r
261         mov     ebx, (k)\r
262         mov     edx, (c)\r
263         mov     esi, (s)\r
264         mov     edi, (d)\r
265         mov     ecx, (l)\r
266         mov     eax, (v)\r
267         NEH_CBC\r
268         mov     esi, eax\r
269         mov     edi, (w)\r
270         movsd\r
271         movsd\r
272         movsd\r
273         movsd\r
274     }\r
275 }\r
276 \r
277 INLINE void via_cfb_op6(\r
278             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
279 {   __asm\r
280     {\r
281         NEH_REKEY\r
282         mov     ebx, (k)\r
283         mov     edx, (c)\r
284         mov     esi, (s)\r
285         mov     edi, (d)\r
286         mov     ecx, (l)\r
287         mov     eax, (v)\r
288         NEH_CFB\r
289     }\r
290 }\r
291 \r
292 INLINE void via_cfb_op7(\r
293         const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\r
294 {   __asm\r
295     {\r
296         NEH_REKEY\r
297         mov     ebx, (k)\r
298         mov     edx, (c)\r
299         mov     esi, (s)\r
300         mov     edi, (d)\r
301         mov     ecx, (l)\r
302         mov     eax, (v)\r
303         NEH_CFB\r
304         mov     esi, eax\r
305         mov     edi, (w)\r
306         movsd\r
307         movsd\r
308         movsd\r
309         movsd\r
310     }\r
311 }\r
312 \r
313 INLINE void via_ofb_op6(\r
314             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
315 {   __asm\r
316     {\r
317         NEH_REKEY\r
318         mov     ebx, (k)\r
319         mov     edx, (c)\r
320         mov     esi, (s)\r
321         mov     edi, (d)\r
322         mov     ecx, (l)\r
323         mov     eax, (v)\r
324         NEH_OFB\r
325     }\r
326 }\r
327 \r
328 #elif defined( __GNUC__ )\r
329 \r
330 #define NEH_REKEY   asm("pushfl\n popfl\n\t")\r
331 #define NEH_ECB     asm(".byte 0xf3, 0x0f, 0xa7, 0xc8\n\t")\r
332 #define NEH_CBC     asm(".byte 0xf3, 0x0f, 0xa7, 0xd0\n\t")\r
333 #define NEH_CFB     asm(".byte 0xf3, 0x0f, 0xa7, 0xe0\n\t")\r
334 #define NEH_OFB     asm(".byte 0xf3, 0x0f, 0xa7, 0xe8\n\t")\r
335 #define NEH_RNG     asm(".byte 0x0f, 0xa7, 0xc0\n\t");\r
336 \r
337 INLINE int has_cpuid(void)\r
338 {   int val;\r
339     asm("pushfl\n\t");\r
340     asm("movl  0(%esp),%eax\n\t");\r
341     asm("xor   $0x00200000,%eax\n\t");\r
342     asm("pushl %eax\n\t");\r
343     asm("popfl\n\t");\r
344     asm("pushfl\n\t");\r
345     asm("popl  %eax\n\t");\r
346     asm("xorl  0(%esp),%edx\n\t");\r
347     asm("andl  $0x00200000,%eax\n\t");\r
348     asm("movl  %%eax,%0\n\t" : "=m" (val));\r
349     asm("popfl\n\t");\r
350     return val ? 1 : 0;\r
351 }\r
352 \r
353 INLINE int is_via_cpu(void)\r
354 {   int val;\r
355     asm("xorl %eax,%eax\n\t");\r
356     asm("cpuid\n\t");\r
357     asm("xorl %eax,%eax\n\t");\r
358     asm("subl $0x746e6543,%ebx\n\t");\r
359     asm("orl  %ebx,%eax\n\t");\r
360     asm("subl $0x48727561,%edx\n\t");\r
361     asm("orl  %edx,%eax\n\t");\r
362     asm("subl $0x736c7561,%ecx\n\t");\r
363     asm("orl  %ecx,%eax\n\t");\r
364     asm("movl %%eax,%0\n\t" : "=m" (val));\r
365     val = (val ? 0 : 1);\r
366     via_flags = (val | NEH_CPU_READ);\r
367     return val;\r
368 }\r
369 \r
370 INLINE int read_via_flags(void)\r
371 {   unsigned char   val;\r
372     asm("movl $0xc0000000,%eax\n\t");\r
373     asm("cpuid\n\t");\r
374     asm("movl $0xc0000001,%edx\n\t");\r
375     asm("cmpl %edx,%eax\n\t");\r
376     asm("setae %al\n\t");\r
377     asm("movb %%al,%0\n\t" : "=m" (val));\r
378     if(!val) return 0;\r
379     asm("movl $0xc0000001,%eax\n\t");\r
380     asm("cpuid\n\t");\r
381     asm("movb %%dl,%0\n\t" : "=m" (val));\r
382     val &= NEH_FLAGS_MASK;\r
383     via_flags |= val;\r
384     return (int) val;\r
385 }\r
386 \r
387 INLINE int via_rng_in(void *buf)\r
388 {   int val;\r
389     asm("pushl %edi\n\t");\r
390     asm("movl %0,%%edi\n\t" : : "m" (buf));\r
391     asm("xorl %edx,%edx\n\t");\r
392     NEH_RNG\r
393     asm("andl $0x0000001f,%eax\n\t");\r
394     asm("movl %%eax,%0\n\t" : "=m" (val));\r
395     asm("popl %edi\n\t");\r
396     return val;\r
397 }\r
398 \r
399 INLINE volatile  void via_ecb_op5(\r
400             const void *k, const void *c, const void *s, void *d, int l)\r
401 {\r
402     NEH_REKEY;\r
403     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
404     asm("movl %0, %%edx\n\t" : : "m" (c));\r
405     asm("movl %0, %%esi\n\t" : : "m" (s));\r
406     asm("movl %0, %%edi\n\t" : : "m" (d));\r
407     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
408     NEH_ECB;\r
409 }\r
410 \r
411 INLINE volatile  void via_cbc_op6(\r
412             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
413 {\r
414     NEH_REKEY;\r
415     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
416     asm("movl %0, %%edx\n\t" : : "m" (c));\r
417     asm("movl %0, %%esi\n\t" : : "m" (s));\r
418     asm("movl %0, %%edi\n\t" : : "m" (d));\r
419     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
420     asm("movl %0, %%eax\n\t" : : "m" (v));\r
421     NEH_CBC;\r
422 }\r
423 \r
424 INLINE volatile  void via_cbc_op7(\r
425         const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\r
426 {\r
427     NEH_REKEY;\r
428     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
429     asm("movl %0, %%edx\n\t" : : "m" (c));\r
430     asm("movl %0, %%esi\n\t" : : "m" (s));\r
431     asm("movl %0, %%edi\n\t" : : "m" (d));\r
432     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
433     asm("movl %0, %%eax\n\t" : : "m" (v));\r
434     NEH_CBC;\r
435     asm("movl %eax,%esi\n\t");\r
436     asm("movl %0, %%edi\n\t" : : "m" (w));\r
437     asm("movsl; movsl; movsl; movsl\n\t");\r
438 }\r
439 \r
440 INLINE volatile  void via_cfb_op6(\r
441             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
442 {\r
443     NEH_REKEY;\r
444     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
445     asm("movl %0, %%edx\n\t" : : "m" (c));\r
446     asm("movl %0, %%esi\n\t" : : "m" (s));\r
447     asm("movl %0, %%edi\n\t" : : "m" (d));\r
448     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
449     asm("movl %0, %%eax\n\t" : : "m" (v));\r
450     NEH_CFB;\r
451 }\r
452 \r
453 INLINE volatile  void via_cfb_op7(\r
454         const void *k, const void *c, const void *s, void *d, int l, void *v, void *w)\r
455 {\r
456     NEH_REKEY;\r
457     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
458     asm("movl %0, %%edx\n\t" : : "m" (c));\r
459     asm("movl %0, %%esi\n\t" : : "m" (s));\r
460     asm("movl %0, %%edi\n\t" : : "m" (d));\r
461     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
462     asm("movl %0, %%eax\n\t" : : "m" (v));\r
463     NEH_CFB;\r
464     asm("movl %eax,%esi\n\t");\r
465     asm("movl %0, %%edi\n\t" : : "m" (w));\r
466     asm("movsl; movsl; movsl; movsl\n\t");\r
467 }\r
468 \r
469 INLINE volatile  void via_ofb_op6(\r
470             const void *k, const void *c, const void *s, void *d, int l, void *v)\r
471 {\r
472     NEH_REKEY;\r
473     asm("movl %0, %%ebx\n\t" : : "m" (k));\r
474     asm("movl %0, %%edx\n\t" : : "m" (c));\r
475     asm("movl %0, %%esi\n\t" : : "m" (s));\r
476     asm("movl %0, %%edi\n\t" : : "m" (d));\r
477     asm("movl %0, %%ecx\n\t" : : "m" (l));\r
478     asm("movl %0, %%eax\n\t" : : "m" (v));\r
479     NEH_OFB;\r
480 }\r
481 \r
482 #else\r
483 #error VIA ACE is not available with this compiler\r
484 #endif\r
485 \r
486 INLINE int via_ace_test(void)\r
487 {\r
488     return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_ACE_FLAGS) == NEH_ACE_FLAGS);\r
489 }\r
490 \r
491 #define VIA_ACE_AVAILABLE   (((via_flags & NEH_ACE_FLAGS) == NEH_ACE_FLAGS)         \\r
492     || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_ace_test())\r
493 \r
494 INLINE int via_rng_test(void)\r
495 {\r
496     return has_cpuid() && is_via_cpu() && ((read_via_flags() & NEH_RNG_FLAGS) == NEH_RNG_FLAGS);\r
497 }\r
498 \r
499 #define VIA_RNG_AVAILABLE   (((via_flags & NEH_RNG_FLAGS) == NEH_RNG_FLAGS)         \\r
500     || (via_flags & NEH_CPU_READ) && (via_flags & NEH_CPU_IS_VIA) || via_rng_test())\r
501 \r
502 INLINE int read_via_rng(void *buf, int count)\r
503 {   int nbr, max_reads, lcnt = count;\r
504     unsigned char *p, *q;\r
505     aligned_auto(unsigned char, bp, 64, 16);\r
506 \r
507     if(!VIA_RNG_AVAILABLE)\r
508         return 0;\r
509 \r
510     do\r
511     {\r
512         max_reads = MAX_READ_ATTEMPTS;\r
513         do\r
514             nbr = via_rng_in(bp);\r
515         while\r
516             (nbr == 0 && --max_reads);\r
517 \r
518         lcnt -= nbr;\r
519         p = (unsigned char*)buf; q = bp;\r
520         while(nbr--)\r
521             *p++ = *q++;\r
522     }\r
523     while\r
524         (lcnt && max_reads);\r
525 \r
526     return count - lcnt;\r
527 }\r
528 \r
529 #endif\r