stop warnings about no previous prototype when compiling shared engines
[openssl.git] / engines / e_padlock.c
1 /* 
2  * Support for VIA PadLock Advanced Cryptography Engine (ACE)
3  * Written by Michal Ludvig <michal@logix.cz>
4  *            http://www.logix.cz/michal
5  *
6  * Big thanks to Andy Polyakov for a help with optimization, 
7  * assembler fixes, port to MS Windows and a lot of other 
8  * valuable work on this engine!
9  */
10
11 /* ====================================================================
12  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  *
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  *
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in
23  *    the documentation and/or other materials provided with the
24  *    distribution.
25  *
26  * 3. All advertising materials mentioning features or use of this
27  *    software must display the following acknowledgment:
28  *    "This product includes software developed by the OpenSSL Project
29  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
30  *
31  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
32  *    endorse or promote products derived from this software without
33  *    prior written permission. For written permission, please contact
34  *    licensing@OpenSSL.org.
35  *
36  * 5. Products derived from this software may not be called "OpenSSL"
37  *    nor may "OpenSSL" appear in their names without prior written
38  *    permission of the OpenSSL Project.
39  *
40  * 6. Redistributions of any form whatsoever must retain the following
41  *    acknowledgment:
42  *    "This product includes software developed by the OpenSSL Project
43  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
46  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
49  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
54  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
56  * OF THE POSSIBILITY OF SUCH DAMAGE.
57  * ====================================================================
58  *
59  * This product includes cryptographic software written by Eric Young
60  * (eay@cryptsoft.com).  This product includes software written by Tim
61  * Hudson (tjh@cryptsoft.com).
62  *
63  */
64
65
66 #include <stdio.h>
67 #include <string.h>
68
69 #include <openssl/opensslconf.h>
70 #include <openssl/crypto.h>
71 #include <openssl/dso.h>
72 #include <openssl/engine.h>
73 #include <openssl/evp.h>
74 #ifndef OPENSSL_NO_AES
75 #include <openssl/aes.h>
76 #endif
77 #include <openssl/rand.h>
78 #include <openssl/err.h>
79
80 #ifndef OPENSSL_NO_HW
81 #ifndef OPENSSL_NO_HW_PADLOCK
82
83 /* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
84 #if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
85 #  ifndef OPENSSL_NO_DYNAMIC_ENGINE
86 #    define DYNAMIC_ENGINE
87 #  endif
88 #elif (OPENSSL_VERSION_NUMBER >= 0x00907000L)
89 #  ifdef ENGINE_DYNAMIC_SUPPORT
90 #    define DYNAMIC_ENGINE
91 #  endif
92 #else
93 #  error "Only OpenSSL >= 0.9.7 is supported"
94 #endif
95
96 /* VIA PadLock AES is available *ONLY* on some x86 CPUs.
97    Not only that it doesn't exist elsewhere, but it
98    even can't be compiled on other platforms!
99  
100    In addition, because of the heavy use of inline assembler,
101    compiler choice is limited to GCC and Microsoft C. */
102 #undef COMPILE_HW_PADLOCK
103 #if !defined(I386_ONLY) && !defined(OPENSSL_NO_INLINE_ASM)
104 # if (defined(__GNUC__) && __GNUC__>=2 && \
105         (defined(__i386__) || defined(__i386) || \
106          defined(__x86_64__) || defined(__x86_64)) \
107      ) || \
108      (defined(_MSC_VER) && defined(_M_IX86))
109 #  define COMPILE_HW_PADLOCK
110 #  ifdef OPENSSL_NO_DYNAMIC_ENGINE
111 static ENGINE *ENGINE_padlock (void);
112 #  endif
113 # endif
114 #endif
115
116 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
117
118 void ENGINE_load_padlock (void)
119 {
120 /* On non-x86 CPUs it just returns. */
121 #ifdef COMPILE_HW_PADLOCK
122         ENGINE *toadd = ENGINE_padlock ();
123         if (!toadd) return;
124         ENGINE_add (toadd);
125         ENGINE_free (toadd);
126         ERR_clear_error ();
127 #endif
128 }
129
130 #endif
131
132 #ifdef COMPILE_HW_PADLOCK
133 /* We do these includes here to avoid header problems on platforms that
134    do not have the VIA padlock anyway... */
135 #include <stdlib.h>
136 #ifdef _WIN32
137 # include <malloc.h>
138 # ifndef alloca
139 #  define alloca _alloca
140 # endif
141 #elif defined(__GNUC__)
142 # ifndef alloca
143 #  define alloca(s) __builtin_alloca((s))
144 # endif
145 #endif
146
147 /* Function for ENGINE detection and control */
148 static int padlock_available(void);
149 static int padlock_init(ENGINE *e);
150
151 /* RNG Stuff */
152 static RAND_METHOD padlock_rand;
153
154 /* Cipher Stuff */
155 #ifndef OPENSSL_NO_AES
156 static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
157 #endif
158
159 /* Engine names */
160 static const char *padlock_id = "padlock";
161 static char padlock_name[100];
162
163 /* Available features */
164 static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
165 static int padlock_use_rng = 0; /* Random Number Generator */
166 #ifndef OPENSSL_NO_AES
167 static int padlock_aes_align_required = 1;
168 #endif
169
170 /* ===== Engine "management" functions ===== */
171
172 /* Prepare the ENGINE structure for registration */
173 static int
174 padlock_bind_helper(ENGINE *e)
175 {
176         /* Check available features */
177         padlock_available();
178
179 #if 1   /* disable RNG for now, see commentary in vicinity of RNG code */
180         padlock_use_rng=0;
181 #endif
182
183         /* Generate a nice engine name with available features */
184         BIO_snprintf(padlock_name, sizeof(padlock_name),
185                 "VIA PadLock (%s, %s)", 
186                  padlock_use_rng ? "RNG" : "no-RNG",
187                  padlock_use_ace ? "ACE" : "no-ACE");
188
189         /* Register everything or return with an error */ 
190         if (!ENGINE_set_id(e, padlock_id) ||
191             !ENGINE_set_name(e, padlock_name) ||
192
193             !ENGINE_set_init_function(e, padlock_init) ||
194 #ifndef OPENSSL_NO_AES
195             (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
196 #endif
197             (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
198                 return 0;
199         }
200
201         /* Everything looks good */
202         return 1;
203 }
204
205 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
206 /* Constructor */
207 static ENGINE *
208 ENGINE_padlock(void)
209 {
210         ENGINE *eng = ENGINE_new();
211
212         if (!eng) {
213                 return NULL;
214         }
215
216         if (!padlock_bind_helper(eng)) {
217                 ENGINE_free(eng);
218                 return NULL;
219         }
220
221         return eng;
222 }
223 #endif
224
225 /* Check availability of the engine */
226 static int
227 padlock_init(ENGINE *e)
228 {
229         return (padlock_use_rng || padlock_use_ace);
230 }
231
232 /* This stuff is needed if this ENGINE is being compiled into a self-contained
233  * shared-library.
234  */
235 #ifdef DYNAMIC_ENGINE
236 static int
237 padlock_bind_fn(ENGINE *e, const char *id)
238 {
239         if (id && (strcmp(id, padlock_id) != 0)) {
240                 return 0;
241         }
242
243         if (!padlock_bind_helper(e))  {
244                 return 0;
245         }
246
247         return 1;
248 }
249
250 IMPLEMENT_DYNAMIC_CHECK_FN()
251 IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn)
252 #endif /* DYNAMIC_ENGINE */
253
254 /* ===== Here comes the "real" engine ===== */
255
256 #ifndef OPENSSL_NO_AES
257 /* Some AES-related constants */
258 #define AES_BLOCK_SIZE          16
259 #define AES_KEY_SIZE_128        16
260 #define AES_KEY_SIZE_192        24
261 #define AES_KEY_SIZE_256        32
262
263 /* Here we store the status information relevant to the 
264    current context. */
265 /* BIG FAT WARNING:
266  *      Inline assembler in PADLOCK_XCRYPT_ASM()
267  *      depends on the order of items in this structure.
268  *      Don't blindly modify, reorder, etc!
269  */
270 struct padlock_cipher_data
271 {
272         unsigned char iv[AES_BLOCK_SIZE];       /* Initialization vector */
273         union { unsigned int pad[4];
274                 struct {
275                         int rounds:4;
276                         int dgst:1;     /* n/a in C3 */
277                         int align:1;    /* n/a in C3 */
278                         int ciphr:1;    /* n/a in C3 */
279                         unsigned int keygen:1;
280                         int interm:1;
281                         unsigned int encdec:1;
282                         int ksize:2;
283                 } b;
284         } cword;                /* Control word */
285         AES_KEY ks;             /* Encryption key */
286 };
287
288 /*
289  * Essentially this variable belongs in thread local storage.
290  * Having this variable global on the other hand can only cause
291  * few bogus key reloads [if any at all on single-CPU system],
292  * so we accept the penatly...
293  */
294 static volatile struct padlock_cipher_data *padlock_saved_context;
295 #endif
296
297 /*
298  * =======================================================
299  * Inline assembler section(s).
300  * =======================================================
301  * Order of arguments is chosen to facilitate Windows port
302  * using __fastcall calling convention. If you wish to add
303  * more routines, keep in mind that first __fastcall
304  * argument is passed in %ecx and second - in %edx.
305  * =======================================================
306  */
307 #if defined(__GNUC__) && __GNUC__>=2
308 #if defined(__i386__) || defined(__i386)
309 /*
310  * As for excessive "push %ebx"/"pop %ebx" found all over.
311  * When generating position-independent code GCC won't let
312  * us use "b" in assembler templates nor even respect "ebx"
313  * in "clobber description." Therefore the trouble...
314  */
315
316 /* Helper function - check if a CPUID instruction
317    is available on this CPU */
318 static int
319 padlock_insn_cpuid_available(void)
320 {
321         int result = -1;
322
323         /* We're checking if the bit #21 of EFLAGS 
324            can be toggled. If yes = CPUID is available. */
325         asm volatile (
326                 "pushf\n"
327                 "popl %%eax\n"
328                 "xorl $0x200000, %%eax\n"
329                 "movl %%eax, %%ecx\n"
330                 "andl $0x200000, %%ecx\n"
331                 "pushl %%eax\n"
332                 "popf\n"
333                 "pushf\n"
334                 "popl %%eax\n"
335                 "andl $0x200000, %%eax\n"
336                 "xorl %%eax, %%ecx\n"
337                 "movl %%ecx, %0\n"
338                 : "=r" (result) : : "eax", "ecx");
339         
340         return (result == 0);
341 }
342
343 /* Load supported features of the CPU to see if
344    the PadLock is available. */
345 static int
346 padlock_available(void)
347 {
348         char vendor_string[16];
349         unsigned int eax, edx;
350
351         /* First check if the CPUID instruction is available at all... */
352         if (! padlock_insn_cpuid_available())
353                 return 0;
354
355         /* Are we running on the Centaur (VIA) CPU? */
356         eax = 0x00000000;
357         vendor_string[12] = 0;
358         asm volatile (
359                 "pushl  %%ebx\n"
360                 "cpuid\n"
361                 "movl   %%ebx,(%%edi)\n"
362                 "movl   %%edx,4(%%edi)\n"
363                 "movl   %%ecx,8(%%edi)\n"
364                 "popl   %%ebx"
365                 : "+a"(eax) : "D"(vendor_string) : "ecx", "edx");
366         if (strcmp(vendor_string, "CentaurHauls") != 0)
367                 return 0;
368
369         /* Check for Centaur Extended Feature Flags presence */
370         eax = 0xC0000000;
371         asm volatile ("pushl %%ebx; cpuid; popl %%ebx"
372                 : "+a"(eax) : : "ecx", "edx");
373         if (eax < 0xC0000001)
374                 return 0;
375
376         /* Read the Centaur Extended Feature Flags */
377         eax = 0xC0000001;
378         asm volatile ("pushl %%ebx; cpuid; popl %%ebx"
379                 : "+a"(eax), "=d"(edx) : : "ecx");
380
381         /* Fill up some flags */
382         padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
383         padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
384
385         return padlock_use_ace + padlock_use_rng;
386 }
387
388 /* Force key reload from memory to the CPU microcode.
389    Loading EFLAGS from the stack clears EFLAGS[30] 
390    which does the trick. */
391 static inline void
392 padlock_reload_key(void)
393 {
394         asm volatile ("pushfl; popfl");
395 }
396
397 #ifndef OPENSSL_NO_AES
398 /*
399  * This is heuristic key context tracing. At first one
400  * believes that one should use atomic swap instructions,
401  * but it's not actually necessary. Point is that if
402  * padlock_saved_context was changed by another thread
403  * after we've read it and before we compare it with cdata,
404  * our key *shall* be reloaded upon thread context switch
405  * and we are therefore set in either case...
406  */
407 static inline void
408 padlock_verify_context(struct padlock_cipher_data *cdata)
409 {
410         asm volatile (
411         "pushfl\n"
412 "       btl     $30,(%%esp)\n"
413 "       jnc     1f\n"
414 "       cmpl    %2,%1\n"
415 "       je      1f\n"
416 "       popfl\n"
417 "       subl    $4,%%esp\n"
418 "1:     addl    $4,%%esp\n"
419 "       movl    %2,%0"
420         :"+m"(padlock_saved_context)
421         : "r"(padlock_saved_context), "r"(cdata) : "cc");
422 }
423
424 /* Template for padlock_xcrypt_* modes */
425 /* BIG FAT WARNING: 
426  *      The offsets used with 'leal' instructions
427  *      describe items of the 'padlock_cipher_data'
428  *      structure.
429  */
430 #define PADLOCK_XCRYPT_ASM(name,rep_xcrypt)     \
431 static inline void *name(size_t cnt,            \
432         struct padlock_cipher_data *cdata,      \
433         void *out, const void *inp)             \
434 {       void *iv;                               \
435         asm volatile ( "pushl   %%ebx\n"        \
436                 "       leal    16(%0),%%edx\n" \
437                 "       leal    32(%0),%%ebx\n" \
438                         rep_xcrypt "\n"         \
439                 "       popl    %%ebx"          \
440                 : "=a"(iv), "=c"(cnt), "=D"(out), "=S"(inp) \
441                 : "0"(cdata), "1"(cnt), "2"(out), "3"(inp)  \
442                 : "edx", "cc", "memory");       \
443         return iv;                              \
444 }
445 #endif
446
447 #elif defined(__x86_64__) || defined(__x86_64)
448
449 /* Load supported features of the CPU to see if
450    the PadLock is available. */
451 static int
452 padlock_available(void)
453 {
454         char vendor_string[16];
455         unsigned int eax, edx;
456
457         /* Are we running on the Centaur (VIA) CPU? */
458         eax = 0x00000000;
459         vendor_string[12] = 0;
460         asm volatile (
461                 "cpuid\n"
462                 "movl   %%ebx,(%1)\n"
463                 "movl   %%edx,4(%1)\n"
464                 "movl   %%ecx,8(%1)\n"
465                 : "+a"(eax) : "r"(vendor_string) : "rbx", "rcx", "rdx");
466         if (strcmp(vendor_string, "CentaurHauls") != 0)
467                 return 0;
468
469         /* Check for Centaur Extended Feature Flags presence */
470         eax = 0xC0000000;
471         asm volatile ("cpuid"
472                 : "+a"(eax) : : "rbx", "rcx", "rdx");
473         if (eax < 0xC0000001)
474                 return 0;
475
476         /* Read the Centaur Extended Feature Flags */
477         eax = 0xC0000001;
478         asm volatile ("cpuid"
479                 : "+a"(eax), "=d"(edx) : : "rbx", "rcx");
480
481         /* Fill up some flags */
482         padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
483         padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
484
485         return padlock_use_ace + padlock_use_rng;
486 }
487
488 /* Force key reload from memory to the CPU microcode.
489    Loading EFLAGS from the stack clears EFLAGS[30] 
490    which does the trick. */
491 static inline void
492 padlock_reload_key(void)
493 {
494         asm volatile ("pushfq; popfq");
495 }
496
497 #ifndef OPENSSL_NO_AES
498 /*
499  * This is heuristic key context tracing. At first one
500  * believes that one should use atomic swap instructions,
501  * but it's not actually necessary. Point is that if
502  * padlock_saved_context was changed by another thread
503  * after we've read it and before we compare it with cdata,
504  * our key *shall* be reloaded upon thread context switch
505  * and we are therefore set in either case...
506  */
507 static inline void
508 padlock_verify_context(struct padlock_cipher_data *cdata)
509 {
510         asm volatile (
511         "pushfq\n"
512 "       btl     $30,(%%rsp)\n"
513 "       jnc     1f\n"
514 "       cmpq    %2,%1\n"
515 "       je      1f\n"
516 "       popfq\n"
517 "       subq    $8,%%rsp\n"
518 "1:     addq    $8,%%rsp\n"
519 "       movq    %2,%0"
520         :"+m"(padlock_saved_context)
521         : "r"(padlock_saved_context), "r"(cdata) : "cc");
522 }
523
524 /* Template for padlock_xcrypt_* modes */
525 /* BIG FAT WARNING: 
526  *      The offsets used with 'leal' instructions
527  *      describe items of the 'padlock_cipher_data'
528  *      structure.
529  */
530 #define PADLOCK_XCRYPT_ASM(name,rep_xcrypt)     \
531 static inline void *name(size_t cnt,            \
532         struct padlock_cipher_data *cdata,      \
533         void *out, const void *inp)             \
534 {       void *iv;                               \
535         asm volatile ( "leaq    16(%0),%%rdx\n" \
536                 "       leaq    32(%0),%%rbx\n" \
537                         rep_xcrypt "\n"         \
538                 : "=a"(iv), "=c"(cnt), "=D"(out), "=S"(inp) \
539                 : "0"(cdata), "1"(cnt), "2"(out), "3"(inp)  \
540                 : "rbx", "rdx", "cc", "memory");        \
541         return iv;                              \
542 }
543 #endif
544
545 #endif  /* cpu */
546
547 #ifndef OPENSSL_NO_AES
548 /* Generate all functions with appropriate opcodes */
549 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb, ".byte 0xf3,0x0f,0xa7,0xc8")     /* rep xcryptecb */
550 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc, ".byte 0xf3,0x0f,0xa7,0xd0")     /* rep xcryptcbc */
551 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb, ".byte 0xf3,0x0f,0xa7,0xe0")     /* rep xcryptcfb */
552 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb, ".byte 0xf3,0x0f,0xa7,0xe8")     /* rep xcryptofb */
553
554 /* Our own htonl()/ntohl() */
555 static inline void
556 padlock_bswapl(AES_KEY *ks)
557 {
558         size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
559         unsigned int *key = ks->rd_key;
560
561         while (i--) {
562                 asm volatile ("bswapl %0" : "+r"(*key));
563                 key++;
564         }
565 }
566 #endif
567
568 /* The RNG call itself */
569 static inline unsigned int
570 padlock_xstore(void *addr, unsigned int edx_in)
571 {
572         unsigned int eax_out;
573
574         asm volatile (".byte 0x0f,0xa7,0xc0"    /* xstore */
575             : "=a"(eax_out),"=m"(*(unsigned *)addr)
576             : "D"(addr), "d" (edx_in)
577             );
578
579         return eax_out;
580 }
581
582 /* Why not inline 'rep movsd'? I failed to find information on what
583  * value in Direction Flag one can expect and consequently have to
584  * apply "better-safe-than-sorry" approach and assume "undefined."
585  * I could explicitly clear it and restore the original value upon
586  * return from padlock_aes_cipher, but it's presumably too much
587  * trouble for too little gain...
588  *
589  * In case you wonder 'rep xcrypt*' instructions above are *not*
590  * affected by the Direction Flag and pointers advance toward
591  * larger addresses unconditionally.
592  */ 
593 static inline unsigned char *
594 padlock_memcpy(void *dst,const void *src,size_t n)
595 {
596         size_t       *d=dst;
597         const size_t *s=src;
598
599         n /= sizeof(*d);
600         do { *d++ = *s++; } while (--n);
601
602         return dst;
603 }
604
605 #elif defined(_MSC_VER)
606 /*
607  * Unlike GCC these are real functions. In order to minimize impact
608  * on performance we adhere to __fastcall calling convention in
609  * order to get two first arguments passed through %ecx and %edx.
610  * Which kind of suits very well, as instructions in question use
611  * both %ecx and %edx as input:-)
612  */
613 #define REP_XCRYPT(code)                \
614         _asm _emit 0xf3                 \
615         _asm _emit 0x0f _asm _emit 0xa7 \
616         _asm _emit code
617
618 /* BIG FAT WARNING: 
619  *      The offsets used with 'lea' instructions
620  *      describe items of the 'padlock_cipher_data'
621  *      structure.
622  */
623 #define PADLOCK_XCRYPT_ASM(name,code)   \
624 static void * __fastcall                \
625         name (size_t cnt, void *cdata,  \
626         void *outp, const void *inp)    \
627 {       _asm    mov     eax,edx         \
628         _asm    lea     edx,[eax+16]    \
629         _asm    lea     ebx,[eax+32]    \
630         _asm    mov     edi,outp        \
631         _asm    mov     esi,inp         \
632         REP_XCRYPT(code)                \
633 }
634
635 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb,0xc8)
636 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc,0xd0)
637 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb,0xe0)
638 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb,0xe8)
639
640 static int __fastcall
641 padlock_xstore(void *outp,unsigned int code)
642 {       _asm    mov     edi,ecx
643         _asm _emit 0x0f _asm _emit 0xa7 _asm _emit 0xc0
644 }
645
646 static void __fastcall
647 padlock_reload_key(void)
648 {       _asm pushfd _asm popfd          }
649
650 static void __fastcall
651 padlock_verify_context(void *cdata)
652 {       _asm    {
653                 pushfd
654                 bt      DWORD PTR[esp],30
655                 jnc     skip
656                 cmp     ecx,padlock_saved_context
657                 je      skip
658                 popfd
659                 sub     esp,4
660         skip:   add     esp,4
661                 mov     padlock_saved_context,ecx
662                 }
663 }
664
665 static int
666 padlock_available(void)
667 {       _asm    {
668                 pushfd
669                 pop     eax
670                 mov     ecx,eax
671                 xor     eax,1<<21
672                 push    eax
673                 popfd
674                 pushfd
675                 pop     eax
676                 xor     eax,ecx
677                 bt      eax,21
678                 jnc     noluck
679                 mov     eax,0
680                 cpuid
681                 xor     eax,eax
682                 cmp     ebx,'tneC'
683                 jne     noluck
684                 cmp     edx,'Hrua'
685                 jne     noluck
686                 cmp     ecx,'slua'
687                 jne     noluck
688                 mov     eax,0xC0000000
689                 cpuid
690                 mov     edx,eax
691                 xor     eax,eax
692                 cmp     edx,0xC0000001
693                 jb      noluck
694                 mov     eax,0xC0000001
695                 cpuid
696                 xor     eax,eax
697                 bt      edx,6
698                 jnc     skip_a
699                 bt      edx,7
700                 jnc     skip_a
701                 mov     padlock_use_ace,1
702                 inc     eax
703         skip_a: bt      edx,2
704                 jnc     skip_r
705                 bt      edx,3
706                 jnc     skip_r
707                 mov     padlock_use_rng,1
708                 inc     eax
709         skip_r:
710         noluck:
711                 }
712 }
713
714 static void __fastcall
715 padlock_bswapl(void *key)
716 {       _asm    {
717                 pushfd
718                 cld
719                 mov     esi,ecx
720                 mov     edi,ecx
721                 mov     ecx,60
722         up:     lodsd
723                 bswap   eax
724                 stosd
725                 loop    up
726                 popfd
727                 }
728 }
729
730 /* MS actually specifies status of Direction Flag and compiler even
731  * manages to compile following as 'rep movsd' all by itself...
732  */
733 #define padlock_memcpy(o,i,n) ((unsigned char *)memcpy((o),(i),(n)&~3U))
734 #endif
735
736 /* ===== AES encryption/decryption ===== */
737 #ifndef OPENSSL_NO_AES
738
739 #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
740 #define NID_aes_128_cfb NID_aes_128_cfb128
741 #endif
742
743 #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
744 #define NID_aes_128_ofb NID_aes_128_ofb128
745 #endif
746
747 #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
748 #define NID_aes_192_cfb NID_aes_192_cfb128
749 #endif
750
751 #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
752 #define NID_aes_192_ofb NID_aes_192_ofb128
753 #endif
754
755 #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
756 #define NID_aes_256_cfb NID_aes_256_cfb128
757 #endif
758
759 #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
760 #define NID_aes_256_ofb NID_aes_256_ofb128
761 #endif
762
763 /* List of supported ciphers. */
764 static int padlock_cipher_nids[] = {
765         NID_aes_128_ecb,
766         NID_aes_128_cbc,
767         NID_aes_128_cfb,
768         NID_aes_128_ofb,
769
770         NID_aes_192_ecb,
771         NID_aes_192_cbc,
772         NID_aes_192_cfb,
773         NID_aes_192_ofb,
774
775         NID_aes_256_ecb,
776         NID_aes_256_cbc,
777         NID_aes_256_cfb,
778         NID_aes_256_ofb,
779 };
780 static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/
781                                       sizeof(padlock_cipher_nids[0]));
782
783 /* Function prototypes ... */
784 static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
785                                 const unsigned char *iv, int enc);
786 static int padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
787                               const unsigned char *in, size_t nbytes);
788
789 #define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) +         \
790         ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
791 #define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
792         NEAREST_ALIGNED(ctx->cipher_data))
793
794 #define EVP_CIPHER_block_size_ECB       AES_BLOCK_SIZE
795 #define EVP_CIPHER_block_size_CBC       AES_BLOCK_SIZE
796 #define EVP_CIPHER_block_size_OFB       1
797 #define EVP_CIPHER_block_size_CFB       1
798
799 /* Declaring so many ciphers by hand would be a pain.
800    Instead introduce a bit of preprocessor magic :-) */
801 #define DECLARE_AES_EVP(ksize,lmode,umode)      \
802 static const EVP_CIPHER padlock_aes_##ksize##_##lmode = {       \
803         NID_aes_##ksize##_##lmode,              \
804         EVP_CIPHER_block_size_##umode,  \
805         AES_KEY_SIZE_##ksize,           \
806         AES_BLOCK_SIZE,                 \
807         0 | EVP_CIPH_##umode##_MODE,    \
808         padlock_aes_init_key,           \
809         padlock_aes_cipher,             \
810         NULL,                           \
811         sizeof(struct padlock_cipher_data) + 16,        \
812         EVP_CIPHER_set_asn1_iv,         \
813         EVP_CIPHER_get_asn1_iv,         \
814         NULL,                           \
815         NULL                            \
816 }
817
818 DECLARE_AES_EVP(128,ecb,ECB);
819 DECLARE_AES_EVP(128,cbc,CBC);
820 DECLARE_AES_EVP(128,cfb,CFB);
821 DECLARE_AES_EVP(128,ofb,OFB);
822
823 DECLARE_AES_EVP(192,ecb,ECB);
824 DECLARE_AES_EVP(192,cbc,CBC);
825 DECLARE_AES_EVP(192,cfb,CFB);
826 DECLARE_AES_EVP(192,ofb,OFB);
827
828 DECLARE_AES_EVP(256,ecb,ECB);
829 DECLARE_AES_EVP(256,cbc,CBC);
830 DECLARE_AES_EVP(256,cfb,CFB);
831 DECLARE_AES_EVP(256,ofb,OFB);
832
833 static int
834 padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
835 {
836         /* No specific cipher => return a list of supported nids ... */
837         if (!cipher) {
838                 *nids = padlock_cipher_nids;
839                 return padlock_cipher_nids_num;
840         }
841
842         /* ... or the requested "cipher" otherwise */
843         switch (nid) {
844           case NID_aes_128_ecb:
845             *cipher = &padlock_aes_128_ecb;
846             break;
847           case NID_aes_128_cbc:
848             *cipher = &padlock_aes_128_cbc;
849             break;
850           case NID_aes_128_cfb:
851             *cipher = &padlock_aes_128_cfb;
852             break;
853           case NID_aes_128_ofb:
854             *cipher = &padlock_aes_128_ofb;
855             break;
856
857           case NID_aes_192_ecb:
858             *cipher = &padlock_aes_192_ecb;
859             break;
860           case NID_aes_192_cbc:
861             *cipher = &padlock_aes_192_cbc;
862             break;
863           case NID_aes_192_cfb:
864             *cipher = &padlock_aes_192_cfb;
865             break;
866           case NID_aes_192_ofb:
867             *cipher = &padlock_aes_192_ofb;
868             break;
869
870           case NID_aes_256_ecb:
871             *cipher = &padlock_aes_256_ecb;
872             break;
873           case NID_aes_256_cbc:
874             *cipher = &padlock_aes_256_cbc;
875             break;
876           case NID_aes_256_cfb:
877             *cipher = &padlock_aes_256_cfb;
878             break;
879           case NID_aes_256_ofb:
880             *cipher = &padlock_aes_256_ofb;
881             break;
882
883           default:
884             /* Sorry, we don't support this NID */
885             *cipher = NULL;
886             return 0;
887         }
888
889         return 1;
890 }
891
892 /* Prepare the encryption key for PadLock usage */
893 static int
894 padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key,
895                       const unsigned char *iv, int enc)
896 {
897         struct padlock_cipher_data *cdata;
898         int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
899
900         if (key==NULL) return 0;        /* ERROR */
901
902         cdata = ALIGNED_CIPHER_DATA(ctx);
903         memset(cdata, 0, sizeof(struct padlock_cipher_data));
904
905         /* Prepare Control word. */
906         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE)
907                 cdata->cword.b.encdec = 0;
908         else
909                 cdata->cword.b.encdec = (ctx->encrypt == 0);
910         cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
911         cdata->cword.b.ksize = (key_len - 128) / 64;
912
913         switch(key_len) {
914                 case 128:
915                         /* PadLock can generate an extended key for
916                            AES128 in hardware */
917                         memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
918                         cdata->cword.b.keygen = 0;
919                         break;
920
921                 case 192:
922                 case 256:
923                         /* Generate an extended AES key in software.
924                            Needed for AES192/AES256 */
925                         /* Well, the above applies to Stepping 8 CPUs
926                            and is listed as hardware errata. They most
927                            likely will fix it at some point and then
928                            a check for stepping would be due here. */
929                         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE ||
930                             EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE ||
931                             enc)
932                                 AES_set_encrypt_key(key, key_len, &cdata->ks);
933                         else
934                                 AES_set_decrypt_key(key, key_len, &cdata->ks);
935 #ifndef AES_ASM
936                         /* OpenSSL C functions use byte-swapped extended key. */
937                         padlock_bswapl(&cdata->ks);
938 #endif
939                         cdata->cword.b.keygen = 1;
940                         break;
941
942                 default:
943                         /* ERROR */
944                         return 0;
945         }
946
947         /*
948          * This is done to cover for cases when user reuses the
949          * context for new key. The catch is that if we don't do
950          * this, padlock_eas_cipher might proceed with old key...
951          */
952         padlock_reload_key ();
953
954         return 1;
955 }
956
957 /* 
958  * Simplified version of padlock_aes_cipher() used when
959  * 1) both input and output buffers are at aligned addresses.
960  * or when
961  * 2) running on a newer CPU that doesn't require aligned buffers.
962  */
963 static int
964 padlock_aes_cipher_omnivorous(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
965                 const unsigned char *in_arg, size_t nbytes)
966 {
967         struct padlock_cipher_data *cdata;
968         void  *iv;
969
970         cdata = ALIGNED_CIPHER_DATA(ctx);
971         padlock_verify_context(cdata);
972
973         switch (EVP_CIPHER_CTX_mode(ctx)) {
974         case EVP_CIPH_ECB_MODE:
975                 padlock_xcrypt_ecb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
976                 break;
977
978         case EVP_CIPH_CBC_MODE:
979                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
980                 iv = padlock_xcrypt_cbc(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
981                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
982                 break;
983
984         case EVP_CIPH_CFB_MODE:
985                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
986                 iv = padlock_xcrypt_cfb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
987                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
988                 break;
989
990         case EVP_CIPH_OFB_MODE:
991                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
992                 padlock_xcrypt_ofb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
993                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
994                 break;
995
996         default:
997                 return 0;
998         }
999
1000         memset(cdata->iv, 0, AES_BLOCK_SIZE);
1001
1002         return 1;
1003 }
1004
1005 #ifndef  PADLOCK_CHUNK
1006 # define PADLOCK_CHUNK  512     /* Must be a power of 2 larger than 16 */
1007 #endif
1008 #if PADLOCK_CHUNK<16 || PADLOCK_CHUNK&(PADLOCK_CHUNK-1)
1009 # error "insane PADLOCK_CHUNK..."
1010 #endif
1011
1012 /* Re-align the arguments to 16-Bytes boundaries and run the 
1013    encryption function itself. This function is not AES-specific. */
1014 static int
1015 padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
1016                    const unsigned char *in_arg, size_t nbytes)
1017 {
1018         struct padlock_cipher_data *cdata;
1019         const  void *inp;
1020         unsigned char  *out;
1021         void  *iv;
1022         int    inp_misaligned, out_misaligned, realign_in_loop;
1023         size_t chunk, allocated=0;
1024
1025         /* ctx->num is maintained in byte-oriented modes,
1026            such as CFB and OFB... */
1027         if ((chunk = ctx->num)) { /* borrow chunk variable */
1028                 unsigned char *ivp=ctx->iv;
1029
1030                 switch (EVP_CIPHER_CTX_mode(ctx)) {
1031                 case EVP_CIPH_CFB_MODE:
1032                         if (chunk >= AES_BLOCK_SIZE)
1033                                 return 0; /* bogus value */
1034
1035                         if (ctx->encrypt)
1036                                 while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1037                                         ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
1038                                         chunk++, nbytes--;
1039                                 }
1040                         else    while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1041                                         unsigned char c = *(in_arg++);
1042                                         *(out_arg++) = c ^ ivp[chunk];
1043                                         ivp[chunk++] = c, nbytes--;
1044                                 }
1045
1046                         ctx->num = chunk%AES_BLOCK_SIZE;
1047                         break;
1048                 case EVP_CIPH_OFB_MODE:
1049                         if (chunk >= AES_BLOCK_SIZE)
1050                                 return 0; /* bogus value */
1051
1052                         while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1053                                 *(out_arg++) = *(in_arg++) ^ ivp[chunk];
1054                                 chunk++, nbytes--;
1055                         }
1056
1057                         ctx->num = chunk%AES_BLOCK_SIZE;
1058                         break;
1059                 }
1060         }
1061
1062         if (nbytes == 0)
1063                 return 1;
1064 #if 0
1065         if (nbytes % AES_BLOCK_SIZE)
1066                 return 0; /* are we expected to do tail processing? */
1067 #else
1068         /* nbytes is always multiple of AES_BLOCK_SIZE in ECB and CBC
1069            modes and arbitrary value in byte-oriented modes, such as
1070            CFB and OFB... */
1071 #endif
1072
1073         /* VIA promises CPUs that won't require alignment in the future.
1074            For now padlock_aes_align_required is initialized to 1 and
1075            the condition is never met... */
1076         /* C7 core is capable to manage unaligned input in non-ECB[!]
1077            mode, but performance penalties appear to be approximately
1078            same as for software alignment below or ~3x. They promise to
1079            improve it in the future, but for now we can just as well
1080            pretend that it can only handle aligned input... */
1081         if (!padlock_aes_align_required && (nbytes%AES_BLOCK_SIZE)==0)
1082                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
1083
1084         inp_misaligned = (((size_t)in_arg) & 0x0F);
1085         out_misaligned = (((size_t)out_arg) & 0x0F);
1086
1087         /* Note that even if output is aligned and input not,
1088          * I still prefer to loop instead of copy the whole
1089          * input and then encrypt in one stroke. This is done
1090          * in order to improve L1 cache utilization... */
1091         realign_in_loop = out_misaligned|inp_misaligned;
1092
1093         if (!realign_in_loop && (nbytes%AES_BLOCK_SIZE)==0)
1094                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
1095
1096         /* this takes one "if" out of the loops */
1097         chunk  = nbytes;
1098         chunk %= PADLOCK_CHUNK;
1099         if (chunk==0) chunk = PADLOCK_CHUNK;
1100
1101         if (out_misaligned) {
1102                 /* optmize for small input */
1103                 allocated = (chunk<nbytes?PADLOCK_CHUNK:nbytes);
1104                 out = alloca(0x10 + allocated);
1105                 out = NEAREST_ALIGNED(out);
1106         }
1107         else
1108                 out = out_arg;
1109
1110         cdata = ALIGNED_CIPHER_DATA(ctx);
1111         padlock_verify_context(cdata);
1112
1113         switch (EVP_CIPHER_CTX_mode(ctx)) {
1114         case EVP_CIPH_ECB_MODE:
1115                 do      {
1116                         if (inp_misaligned)
1117                                 inp = padlock_memcpy(out, in_arg, chunk);
1118                         else
1119                                 inp = in_arg;
1120                         in_arg += chunk;
1121
1122                         padlock_xcrypt_ecb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1123
1124                         if (out_misaligned)
1125                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1126                         else
1127                                 out     = out_arg+=chunk;
1128
1129                         nbytes -= chunk;
1130                         chunk   = PADLOCK_CHUNK;
1131                 } while (nbytes);
1132                 break;
1133
1134         case EVP_CIPH_CBC_MODE:
1135                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1136                 goto cbc_shortcut;
1137                 do      {
1138                         if (iv != cdata->iv)
1139                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1140                         chunk = PADLOCK_CHUNK;
1141                 cbc_shortcut: /* optimize for small input */
1142                         if (inp_misaligned)
1143                                 inp = padlock_memcpy(out, in_arg, chunk);
1144                         else
1145                                 inp = in_arg;
1146                         in_arg += chunk;
1147
1148                         iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1149
1150                         if (out_misaligned)
1151                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1152                         else
1153                                 out     = out_arg+=chunk;
1154
1155                 } while (nbytes -= chunk);
1156                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1157                 break;
1158
1159         case EVP_CIPH_CFB_MODE:
1160                 memcpy (iv = cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1161                 chunk &= ~(AES_BLOCK_SIZE-1);
1162                 if (chunk)      goto cfb_shortcut;
1163                 else            goto cfb_skiploop;
1164                 do      {
1165                         if (iv != cdata->iv)
1166                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1167                         chunk = PADLOCK_CHUNK;
1168                 cfb_shortcut: /* optimize for small input */
1169                         if (inp_misaligned)
1170                                 inp = padlock_memcpy(out, in_arg, chunk);
1171                         else
1172                                 inp = in_arg;
1173                         in_arg += chunk;
1174
1175                         iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1176
1177                         if (out_misaligned)
1178                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1179                         else
1180                                 out     = out_arg+=chunk;
1181
1182                         nbytes -= chunk;
1183                 } while (nbytes >= AES_BLOCK_SIZE);
1184
1185                 cfb_skiploop:
1186                 if (nbytes) {
1187                         unsigned char *ivp = cdata->iv;
1188
1189                         if (iv != ivp) {
1190                                 memcpy(ivp, iv, AES_BLOCK_SIZE);
1191                                 iv = ivp;
1192                         }
1193                         ctx->num = nbytes;
1194                         if (cdata->cword.b.encdec) {
1195                                 cdata->cword.b.encdec=0;
1196                                 padlock_reload_key();
1197                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1198                                 cdata->cword.b.encdec=1;
1199                                 padlock_reload_key();
1200                                 while(nbytes) {
1201                                         unsigned char c = *(in_arg++);
1202                                         *(out_arg++) = c ^ *ivp;
1203                                         *(ivp++) = c, nbytes--;
1204                                 }
1205                         }
1206                         else {  padlock_reload_key();
1207                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1208                                 padlock_reload_key();
1209                                 while (nbytes) {
1210                                         *ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
1211                                         ivp++, nbytes--;
1212                                 }
1213                         }
1214                 }
1215
1216                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1217                 break;
1218
1219         case EVP_CIPH_OFB_MODE:
1220                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1221                 chunk &= ~(AES_BLOCK_SIZE-1);
1222                 if (chunk) do   {
1223                         if (inp_misaligned)
1224                                 inp = padlock_memcpy(out, in_arg, chunk);
1225                         else
1226                                 inp = in_arg;
1227                         in_arg += chunk;
1228
1229                         padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1230
1231                         if (out_misaligned)
1232                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1233                         else
1234                                 out     = out_arg+=chunk;
1235
1236                         nbytes -= chunk;
1237                         chunk   = PADLOCK_CHUNK;
1238                 } while (nbytes >= AES_BLOCK_SIZE);
1239
1240                 if (nbytes) {
1241                         unsigned char *ivp = cdata->iv;
1242
1243                         ctx->num = nbytes;
1244                         padlock_reload_key();   /* empirically found */
1245                         padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1246                         padlock_reload_key();   /* empirically found */
1247                         while (nbytes) {
1248                                 *(out_arg++) = *(in_arg++) ^ *ivp;
1249                                 ivp++, nbytes--;
1250                         }
1251                 }
1252
1253                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
1254                 break;
1255
1256         default:
1257                 return 0;
1258         }
1259
1260         /* Clean the realign buffer if it was used */
1261         if (out_misaligned) {
1262                 volatile unsigned long *p=(void *)out;
1263                 size_t   n = allocated/sizeof(*p);
1264                 while (n--) *p++=0;
1265         }
1266
1267         memset(cdata->iv, 0, AES_BLOCK_SIZE);
1268
1269         return 1;
1270 }
1271
1272 #endif /* OPENSSL_NO_AES */
1273
1274 /* ===== Random Number Generator ===== */
1275 /*
1276  * This code is not engaged. The reason is that it does not comply
1277  * with recommendations for VIA RNG usage for secure applications
1278  * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
1279  * provide meaningful error control...
1280  */
1281 /* Wrapper that provides an interface between the API and 
1282    the raw PadLock RNG */
1283 static int
1284 padlock_rand_bytes(unsigned char *output, int count)
1285 {
1286         unsigned int eax, buf;
1287
1288         while (count >= 8) {
1289                 eax = padlock_xstore(output, 0);
1290                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1291                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1292                 if (eax&(0x1F<<10))     return 0;
1293                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1294                 if ((eax&0x1F)!=8)      return 0; /* fatal failure...  */
1295                 output += 8;
1296                 count  -= 8;
1297         }
1298         while (count > 0) {
1299                 eax = padlock_xstore(&buf, 3);
1300                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1301                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1302                 if (eax&(0x1F<<10))     return 0;
1303                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1304                 if ((eax&0x1F)!=1)      return 0; /* fatal failure...  */
1305                 *output++ = (unsigned char)buf;
1306                 count--;
1307         }
1308         *(volatile unsigned int *)&buf=0;
1309
1310         return 1;
1311 }
1312
1313 /* Dummy but necessary function */
1314 static int
1315 padlock_rand_status(void)
1316 {
1317         return 1;
1318 }
1319
1320 /* Prepare structure for registration */
1321 static RAND_METHOD padlock_rand = {
1322         NULL,                   /* seed */
1323         padlock_rand_bytes,     /* bytes */
1324         NULL,                   /* cleanup */
1325         NULL,                   /* add */
1326         padlock_rand_bytes,     /* pseudorand */
1327         padlock_rand_status,    /* rand status */
1328 };
1329
1330 #else  /* !COMPILE_HW_PADLOCK */
1331 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1332 OPENSSL_EXPORT
1333 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
1334 OPENSSL_EXPORT
1335 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
1336 IMPLEMENT_DYNAMIC_CHECK_FN()
1337 #endif
1338 #endif /* COMPILE_HW_PADLOCK */
1339
1340 #endif /* !OPENSSL_NO_HW_PADLOCK */
1341 #endif /* !OPENSSL_NO_HW */