e_padlock.c: make it compile on MacOS X.
[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                 "pushq  %%rbx\n"
462                 "cpuid\n"
463                 "movl   %%ebx,(%1)\n"
464                 "movl   %%edx,4(%1)\n"
465                 "movl   %%ecx,8(%1)\n"
466                 "popq   %%rbx"
467                 : "+a"(eax) : "r"(vendor_string) : "rcx", "rdx");
468         if (strcmp(vendor_string, "CentaurHauls") != 0)
469                 return 0;
470
471         /* Check for Centaur Extended Feature Flags presence */
472         eax = 0xC0000000;
473         asm volatile ("pushq %%rbx; cpuid; popq %%rbx"
474                 : "+a"(eax) : : "rcx", "rdx");
475         if (eax < 0xC0000001)
476                 return 0;
477
478         /* Read the Centaur Extended Feature Flags */
479         eax = 0xC0000001;
480         asm volatile ("pushq %%rbx; cpuid; popq %%rbx"
481                 : "+a"(eax), "=d"(edx) : : "rcx");
482
483         /* Fill up some flags */
484         padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
485         padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
486
487         return padlock_use_ace + padlock_use_rng;
488 }
489
490 /* Force key reload from memory to the CPU microcode.
491    Loading EFLAGS from the stack clears EFLAGS[30] 
492    which does the trick. */
493 static inline void
494 padlock_reload_key(void)
495 {
496         asm volatile ("pushfq; popfq");
497 }
498
499 #ifndef OPENSSL_NO_AES
500 /*
501  * This is heuristic key context tracing. At first one
502  * believes that one should use atomic swap instructions,
503  * but it's not actually necessary. Point is that if
504  * padlock_saved_context was changed by another thread
505  * after we've read it and before we compare it with cdata,
506  * our key *shall* be reloaded upon thread context switch
507  * and we are therefore set in either case...
508  */
509 static inline void
510 padlock_verify_context(struct padlock_cipher_data *cdata)
511 {
512         asm volatile (
513         "pushfq\n"
514 "       btl     $30,(%%rsp)\n"
515 "       jnc     1f\n"
516 "       cmpq    %2,%1\n"
517 "       je      1f\n"
518 "       popfq\n"
519 "       subq    $8,%%rsp\n"
520 "1:     addq    $8,%%rsp\n"
521 "       movq    %2,%0"
522         :"+m"(padlock_saved_context)
523         : "r"(padlock_saved_context), "r"(cdata) : "cc");
524 }
525
526 /* Template for padlock_xcrypt_* modes */
527 /* BIG FAT WARNING: 
528  *      The offsets used with 'leal' instructions
529  *      describe items of the 'padlock_cipher_data'
530  *      structure.
531  */
532 #define PADLOCK_XCRYPT_ASM(name,rep_xcrypt)     \
533 static inline void *name(size_t cnt,            \
534         struct padlock_cipher_data *cdata,      \
535         void *out, const void *inp)             \
536 {       void *iv;                               \
537         asm volatile ( "pushq   %%rbx\n"        \
538                 "       leaq    16(%0),%%rdx\n" \
539                 "       leaq    32(%0),%%rbx\n" \
540                         rep_xcrypt "\n"         \
541                 "       popq    %%rbx"          \
542                 : "=a"(iv), "=c"(cnt), "=D"(out), "=S"(inp) \
543                 : "0"(cdata), "1"(cnt), "2"(out), "3"(inp)  \
544                 : "rdx", "cc", "memory");       \
545         return iv;                              \
546 }
547 #endif
548
549 #endif  /* cpu */
550
551 #ifndef OPENSSL_NO_AES
552 /* Generate all functions with appropriate opcodes */
553 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb, ".byte 0xf3,0x0f,0xa7,0xc8")     /* rep xcryptecb */
554 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc, ".byte 0xf3,0x0f,0xa7,0xd0")     /* rep xcryptcbc */
555 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb, ".byte 0xf3,0x0f,0xa7,0xe0")     /* rep xcryptcfb */
556 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb, ".byte 0xf3,0x0f,0xa7,0xe8")     /* rep xcryptofb */
557
558 /* Our own htonl()/ntohl() */
559 static inline void
560 padlock_bswapl(AES_KEY *ks)
561 {
562         size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
563         unsigned int *key = ks->rd_key;
564
565         while (i--) {
566                 asm volatile ("bswapl %0" : "+r"(*key));
567                 key++;
568         }
569 }
570 #endif
571
572 /* The RNG call itself */
573 static inline unsigned int
574 padlock_xstore(void *addr, unsigned int edx_in)
575 {
576         unsigned int eax_out;
577
578         asm volatile (".byte 0x0f,0xa7,0xc0"    /* xstore */
579             : "=a"(eax_out),"=m"(*(unsigned *)addr)
580             : "D"(addr), "d" (edx_in)
581             );
582
583         return eax_out;
584 }
585
586 /* Why not inline 'rep movsd'? I failed to find information on what
587  * value in Direction Flag one can expect and consequently have to
588  * apply "better-safe-than-sorry" approach and assume "undefined."
589  * I could explicitly clear it and restore the original value upon
590  * return from padlock_aes_cipher, but it's presumably too much
591  * trouble for too little gain...
592  *
593  * In case you wonder 'rep xcrypt*' instructions above are *not*
594  * affected by the Direction Flag and pointers advance toward
595  * larger addresses unconditionally.
596  */ 
597 static inline unsigned char *
598 padlock_memcpy(void *dst,const void *src,size_t n)
599 {
600         size_t       *d=dst;
601         const size_t *s=src;
602
603         n /= sizeof(*d);
604         do { *d++ = *s++; } while (--n);
605
606         return dst;
607 }
608
609 #elif defined(_MSC_VER)
610 /*
611  * Unlike GCC these are real functions. In order to minimize impact
612  * on performance we adhere to __fastcall calling convention in
613  * order to get two first arguments passed through %ecx and %edx.
614  * Which kind of suits very well, as instructions in question use
615  * both %ecx and %edx as input:-)
616  */
617 #define REP_XCRYPT(code)                \
618         _asm _emit 0xf3                 \
619         _asm _emit 0x0f _asm _emit 0xa7 \
620         _asm _emit code
621
622 /* BIG FAT WARNING: 
623  *      The offsets used with 'lea' instructions
624  *      describe items of the 'padlock_cipher_data'
625  *      structure.
626  */
627 #define PADLOCK_XCRYPT_ASM(name,code)   \
628 static void * __fastcall                \
629         name (size_t cnt, void *cdata,  \
630         void *outp, const void *inp)    \
631 {       _asm    mov     eax,edx         \
632         _asm    lea     edx,[eax+16]    \
633         _asm    lea     ebx,[eax+32]    \
634         _asm    mov     edi,outp        \
635         _asm    mov     esi,inp         \
636         REP_XCRYPT(code)                \
637 }
638
639 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb,0xc8)
640 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc,0xd0)
641 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb,0xe0)
642 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb,0xe8)
643
644 static int __fastcall
645 padlock_xstore(void *outp,unsigned int code)
646 {       _asm    mov     edi,ecx
647         _asm _emit 0x0f _asm _emit 0xa7 _asm _emit 0xc0
648 }
649
650 static void __fastcall
651 padlock_reload_key(void)
652 {       _asm pushfd _asm popfd          }
653
654 static void __fastcall
655 padlock_verify_context(void *cdata)
656 {       _asm    {
657                 pushfd
658                 bt      DWORD PTR[esp],30
659                 jnc     skip
660                 cmp     ecx,padlock_saved_context
661                 je      skip
662                 popfd
663                 sub     esp,4
664         skip:   add     esp,4
665                 mov     padlock_saved_context,ecx
666                 }
667 }
668
669 static int
670 padlock_available(void)
671 {       _asm    {
672                 pushfd
673                 pop     eax
674                 mov     ecx,eax
675                 xor     eax,1<<21
676                 push    eax
677                 popfd
678                 pushfd
679                 pop     eax
680                 xor     eax,ecx
681                 bt      eax,21
682                 jnc     noluck
683                 mov     eax,0
684                 cpuid
685                 xor     eax,eax
686                 cmp     ebx,'tneC'
687                 jne     noluck
688                 cmp     edx,'Hrua'
689                 jne     noluck
690                 cmp     ecx,'slua'
691                 jne     noluck
692                 mov     eax,0xC0000000
693                 cpuid
694                 mov     edx,eax
695                 xor     eax,eax
696                 cmp     edx,0xC0000001
697                 jb      noluck
698                 mov     eax,0xC0000001
699                 cpuid
700                 xor     eax,eax
701                 bt      edx,6
702                 jnc     skip_a
703                 bt      edx,7
704                 jnc     skip_a
705                 mov     padlock_use_ace,1
706                 inc     eax
707         skip_a: bt      edx,2
708                 jnc     skip_r
709                 bt      edx,3
710                 jnc     skip_r
711                 mov     padlock_use_rng,1
712                 inc     eax
713         skip_r:
714         noluck:
715                 }
716 }
717
718 static void __fastcall
719 padlock_bswapl(void *key)
720 {       _asm    {
721                 pushfd
722                 cld
723                 mov     esi,ecx
724                 mov     edi,ecx
725                 mov     ecx,60
726         up:     lodsd
727                 bswap   eax
728                 stosd
729                 loop    up
730                 popfd
731                 }
732 }
733
734 /* MS actually specifies status of Direction Flag and compiler even
735  * manages to compile following as 'rep movsd' all by itself...
736  */
737 #define padlock_memcpy(o,i,n) ((unsigned char *)memcpy((o),(i),(n)&~3U))
738 #endif
739
740 /* ===== AES encryption/decryption ===== */
741 #ifndef OPENSSL_NO_AES
742
743 #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
744 #define NID_aes_128_cfb NID_aes_128_cfb128
745 #endif
746
747 #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
748 #define NID_aes_128_ofb NID_aes_128_ofb128
749 #endif
750
751 #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
752 #define NID_aes_192_cfb NID_aes_192_cfb128
753 #endif
754
755 #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
756 #define NID_aes_192_ofb NID_aes_192_ofb128
757 #endif
758
759 #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
760 #define NID_aes_256_cfb NID_aes_256_cfb128
761 #endif
762
763 #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
764 #define NID_aes_256_ofb NID_aes_256_ofb128
765 #endif
766
767 /* List of supported ciphers. */
768 static int padlock_cipher_nids[] = {
769         NID_aes_128_ecb,
770         NID_aes_128_cbc,
771         NID_aes_128_cfb,
772         NID_aes_128_ofb,
773
774         NID_aes_192_ecb,
775         NID_aes_192_cbc,
776         NID_aes_192_cfb,
777         NID_aes_192_ofb,
778
779         NID_aes_256_ecb,
780         NID_aes_256_cbc,
781         NID_aes_256_cfb,
782         NID_aes_256_ofb,
783 };
784 static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/
785                                       sizeof(padlock_cipher_nids[0]));
786
787 /* Function prototypes ... */
788 static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
789                                 const unsigned char *iv, int enc);
790 static int padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
791                               const unsigned char *in, size_t nbytes);
792
793 #define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) +         \
794         ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
795 #define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
796         NEAREST_ALIGNED(ctx->cipher_data))
797
798 #define EVP_CIPHER_block_size_ECB       AES_BLOCK_SIZE
799 #define EVP_CIPHER_block_size_CBC       AES_BLOCK_SIZE
800 #define EVP_CIPHER_block_size_OFB       1
801 #define EVP_CIPHER_block_size_CFB       1
802
803 /* Declaring so many ciphers by hand would be a pain.
804    Instead introduce a bit of preprocessor magic :-) */
805 #define DECLARE_AES_EVP(ksize,lmode,umode)      \
806 static const EVP_CIPHER padlock_aes_##ksize##_##lmode = {       \
807         NID_aes_##ksize##_##lmode,              \
808         EVP_CIPHER_block_size_##umode,  \
809         AES_KEY_SIZE_##ksize,           \
810         AES_BLOCK_SIZE,                 \
811         0 | EVP_CIPH_##umode##_MODE,    \
812         padlock_aes_init_key,           \
813         padlock_aes_cipher,             \
814         NULL,                           \
815         sizeof(struct padlock_cipher_data) + 16,        \
816         EVP_CIPHER_set_asn1_iv,         \
817         EVP_CIPHER_get_asn1_iv,         \
818         NULL,                           \
819         NULL                            \
820 }
821
822 DECLARE_AES_EVP(128,ecb,ECB);
823 DECLARE_AES_EVP(128,cbc,CBC);
824 DECLARE_AES_EVP(128,cfb,CFB);
825 DECLARE_AES_EVP(128,ofb,OFB);
826
827 DECLARE_AES_EVP(192,ecb,ECB);
828 DECLARE_AES_EVP(192,cbc,CBC);
829 DECLARE_AES_EVP(192,cfb,CFB);
830 DECLARE_AES_EVP(192,ofb,OFB);
831
832 DECLARE_AES_EVP(256,ecb,ECB);
833 DECLARE_AES_EVP(256,cbc,CBC);
834 DECLARE_AES_EVP(256,cfb,CFB);
835 DECLARE_AES_EVP(256,ofb,OFB);
836
837 static int
838 padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
839 {
840         /* No specific cipher => return a list of supported nids ... */
841         if (!cipher) {
842                 *nids = padlock_cipher_nids;
843                 return padlock_cipher_nids_num;
844         }
845
846         /* ... or the requested "cipher" otherwise */
847         switch (nid) {
848           case NID_aes_128_ecb:
849             *cipher = &padlock_aes_128_ecb;
850             break;
851           case NID_aes_128_cbc:
852             *cipher = &padlock_aes_128_cbc;
853             break;
854           case NID_aes_128_cfb:
855             *cipher = &padlock_aes_128_cfb;
856             break;
857           case NID_aes_128_ofb:
858             *cipher = &padlock_aes_128_ofb;
859             break;
860
861           case NID_aes_192_ecb:
862             *cipher = &padlock_aes_192_ecb;
863             break;
864           case NID_aes_192_cbc:
865             *cipher = &padlock_aes_192_cbc;
866             break;
867           case NID_aes_192_cfb:
868             *cipher = &padlock_aes_192_cfb;
869             break;
870           case NID_aes_192_ofb:
871             *cipher = &padlock_aes_192_ofb;
872             break;
873
874           case NID_aes_256_ecb:
875             *cipher = &padlock_aes_256_ecb;
876             break;
877           case NID_aes_256_cbc:
878             *cipher = &padlock_aes_256_cbc;
879             break;
880           case NID_aes_256_cfb:
881             *cipher = &padlock_aes_256_cfb;
882             break;
883           case NID_aes_256_ofb:
884             *cipher = &padlock_aes_256_ofb;
885             break;
886
887           default:
888             /* Sorry, we don't support this NID */
889             *cipher = NULL;
890             return 0;
891         }
892
893         return 1;
894 }
895
896 /* Prepare the encryption key for PadLock usage */
897 static int
898 padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key,
899                       const unsigned char *iv, int enc)
900 {
901         struct padlock_cipher_data *cdata;
902         int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
903
904         if (key==NULL) return 0;        /* ERROR */
905
906         cdata = ALIGNED_CIPHER_DATA(ctx);
907         memset(cdata, 0, sizeof(struct padlock_cipher_data));
908
909         /* Prepare Control word. */
910         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE)
911                 cdata->cword.b.encdec = 0;
912         else
913                 cdata->cword.b.encdec = (ctx->encrypt == 0);
914         cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
915         cdata->cword.b.ksize = (key_len - 128) / 64;
916
917         switch(key_len) {
918                 case 128:
919                         /* PadLock can generate an extended key for
920                            AES128 in hardware */
921                         memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
922                         cdata->cword.b.keygen = 0;
923                         break;
924
925                 case 192:
926                 case 256:
927                         /* Generate an extended AES key in software.
928                            Needed for AES192/AES256 */
929                         /* Well, the above applies to Stepping 8 CPUs
930                            and is listed as hardware errata. They most
931                            likely will fix it at some point and then
932                            a check for stepping would be due here. */
933                         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE ||
934                             EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE ||
935                             enc)
936                                 AES_set_encrypt_key(key, key_len, &cdata->ks);
937                         else
938                                 AES_set_decrypt_key(key, key_len, &cdata->ks);
939 #ifndef AES_ASM
940                         /* OpenSSL C functions use byte-swapped extended key. */
941                         padlock_bswapl(&cdata->ks);
942 #endif
943                         cdata->cword.b.keygen = 1;
944                         break;
945
946                 default:
947                         /* ERROR */
948                         return 0;
949         }
950
951         /*
952          * This is done to cover for cases when user reuses the
953          * context for new key. The catch is that if we don't do
954          * this, padlock_eas_cipher might proceed with old key...
955          */
956         padlock_reload_key ();
957
958         return 1;
959 }
960
961 /* 
962  * Simplified version of padlock_aes_cipher() used when
963  * 1) both input and output buffers are at aligned addresses.
964  * or when
965  * 2) running on a newer CPU that doesn't require aligned buffers.
966  */
967 static int
968 padlock_aes_cipher_omnivorous(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
969                 const unsigned char *in_arg, size_t nbytes)
970 {
971         struct padlock_cipher_data *cdata;
972         void  *iv;
973
974         cdata = ALIGNED_CIPHER_DATA(ctx);
975         padlock_verify_context(cdata);
976
977         switch (EVP_CIPHER_CTX_mode(ctx)) {
978         case EVP_CIPH_ECB_MODE:
979                 padlock_xcrypt_ecb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
980                 break;
981
982         case EVP_CIPH_CBC_MODE:
983                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
984                 iv = padlock_xcrypt_cbc(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
985                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
986                 break;
987
988         case EVP_CIPH_CFB_MODE:
989                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
990                 iv = padlock_xcrypt_cfb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
991                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
992                 break;
993
994         case EVP_CIPH_OFB_MODE:
995                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
996                 padlock_xcrypt_ofb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
997                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
998                 break;
999
1000         default:
1001                 return 0;
1002         }
1003
1004         memset(cdata->iv, 0, AES_BLOCK_SIZE);
1005
1006         return 1;
1007 }
1008
1009 #ifndef  PADLOCK_CHUNK
1010 # define PADLOCK_CHUNK  512     /* Must be a power of 2 larger than 16 */
1011 #endif
1012 #if PADLOCK_CHUNK<16 || PADLOCK_CHUNK&(PADLOCK_CHUNK-1)
1013 # error "insane PADLOCK_CHUNK..."
1014 #endif
1015
1016 /* Re-align the arguments to 16-Bytes boundaries and run the 
1017    encryption function itself. This function is not AES-specific. */
1018 static int
1019 padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
1020                    const unsigned char *in_arg, size_t nbytes)
1021 {
1022         struct padlock_cipher_data *cdata;
1023         const  void *inp;
1024         unsigned char  *out;
1025         void  *iv;
1026         int    inp_misaligned, out_misaligned, realign_in_loop;
1027         size_t chunk, allocated=0;
1028
1029         /* ctx->num is maintained in byte-oriented modes,
1030            such as CFB and OFB... */
1031         if ((chunk = ctx->num)) { /* borrow chunk variable */
1032                 unsigned char *ivp=ctx->iv;
1033
1034                 switch (EVP_CIPHER_CTX_mode(ctx)) {
1035                 case EVP_CIPH_CFB_MODE:
1036                         if (chunk >= AES_BLOCK_SIZE)
1037                                 return 0; /* bogus value */
1038
1039                         if (ctx->encrypt)
1040                                 while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1041                                         ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
1042                                         chunk++, nbytes--;
1043                                 }
1044                         else    while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1045                                         unsigned char c = *(in_arg++);
1046                                         *(out_arg++) = c ^ ivp[chunk];
1047                                         ivp[chunk++] = c, nbytes--;
1048                                 }
1049
1050                         ctx->num = chunk%AES_BLOCK_SIZE;
1051                         break;
1052                 case EVP_CIPH_OFB_MODE:
1053                         if (chunk >= AES_BLOCK_SIZE)
1054                                 return 0; /* bogus value */
1055
1056                         while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
1057                                 *(out_arg++) = *(in_arg++) ^ ivp[chunk];
1058                                 chunk++, nbytes--;
1059                         }
1060
1061                         ctx->num = chunk%AES_BLOCK_SIZE;
1062                         break;
1063                 }
1064         }
1065
1066         if (nbytes == 0)
1067                 return 1;
1068 #if 0
1069         if (nbytes % AES_BLOCK_SIZE)
1070                 return 0; /* are we expected to do tail processing? */
1071 #else
1072         /* nbytes is always multiple of AES_BLOCK_SIZE in ECB and CBC
1073            modes and arbitrary value in byte-oriented modes, such as
1074            CFB and OFB... */
1075 #endif
1076
1077         /* VIA promises CPUs that won't require alignment in the future.
1078            For now padlock_aes_align_required is initialized to 1 and
1079            the condition is never met... */
1080         /* C7 core is capable to manage unaligned input in non-ECB[!]
1081            mode, but performance penalties appear to be approximately
1082            same as for software alignment below or ~3x. They promise to
1083            improve it in the future, but for now we can just as well
1084            pretend that it can only handle aligned input... */
1085         if (!padlock_aes_align_required && (nbytes%AES_BLOCK_SIZE)==0)
1086                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
1087
1088         inp_misaligned = (((size_t)in_arg) & 0x0F);
1089         out_misaligned = (((size_t)out_arg) & 0x0F);
1090
1091         /* Note that even if output is aligned and input not,
1092          * I still prefer to loop instead of copy the whole
1093          * input and then encrypt in one stroke. This is done
1094          * in order to improve L1 cache utilization... */
1095         realign_in_loop = out_misaligned|inp_misaligned;
1096
1097         if (!realign_in_loop && (nbytes%AES_BLOCK_SIZE)==0)
1098                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
1099
1100         /* this takes one "if" out of the loops */
1101         chunk  = nbytes;
1102         chunk %= PADLOCK_CHUNK;
1103         if (chunk==0) chunk = PADLOCK_CHUNK;
1104
1105         if (out_misaligned) {
1106                 /* optmize for small input */
1107                 allocated = (chunk<nbytes?PADLOCK_CHUNK:nbytes);
1108                 out = alloca(0x10 + allocated);
1109                 out = NEAREST_ALIGNED(out);
1110         }
1111         else
1112                 out = out_arg;
1113
1114         cdata = ALIGNED_CIPHER_DATA(ctx);
1115         padlock_verify_context(cdata);
1116
1117         switch (EVP_CIPHER_CTX_mode(ctx)) {
1118         case EVP_CIPH_ECB_MODE:
1119                 do      {
1120                         if (inp_misaligned)
1121                                 inp = padlock_memcpy(out, in_arg, chunk);
1122                         else
1123                                 inp = in_arg;
1124                         in_arg += chunk;
1125
1126                         padlock_xcrypt_ecb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1127
1128                         if (out_misaligned)
1129                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1130                         else
1131                                 out     = out_arg+=chunk;
1132
1133                         nbytes -= chunk;
1134                         chunk   = PADLOCK_CHUNK;
1135                 } while (nbytes);
1136                 break;
1137
1138         case EVP_CIPH_CBC_MODE:
1139                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1140                 goto cbc_shortcut;
1141                 do      {
1142                         if (iv != cdata->iv)
1143                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1144                         chunk = PADLOCK_CHUNK;
1145                 cbc_shortcut: /* optimize for small input */
1146                         if (inp_misaligned)
1147                                 inp = padlock_memcpy(out, in_arg, chunk);
1148                         else
1149                                 inp = in_arg;
1150                         in_arg += chunk;
1151
1152                         iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1153
1154                         if (out_misaligned)
1155                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1156                         else
1157                                 out     = out_arg+=chunk;
1158
1159                 } while (nbytes -= chunk);
1160                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1161                 break;
1162
1163         case EVP_CIPH_CFB_MODE:
1164                 memcpy (iv = cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1165                 chunk &= ~(AES_BLOCK_SIZE-1);
1166                 if (chunk)      goto cfb_shortcut;
1167                 else            goto cfb_skiploop;
1168                 do      {
1169                         if (iv != cdata->iv)
1170                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1171                         chunk = PADLOCK_CHUNK;
1172                 cfb_shortcut: /* optimize for small input */
1173                         if (inp_misaligned)
1174                                 inp = padlock_memcpy(out, in_arg, chunk);
1175                         else
1176                                 inp = in_arg;
1177                         in_arg += chunk;
1178
1179                         iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1180
1181                         if (out_misaligned)
1182                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1183                         else
1184                                 out     = out_arg+=chunk;
1185
1186                         nbytes -= chunk;
1187                 } while (nbytes >= AES_BLOCK_SIZE);
1188
1189                 cfb_skiploop:
1190                 if (nbytes) {
1191                         unsigned char *ivp = cdata->iv;
1192
1193                         if (iv != ivp) {
1194                                 memcpy(ivp, iv, AES_BLOCK_SIZE);
1195                                 iv = ivp;
1196                         }
1197                         ctx->num = nbytes;
1198                         if (cdata->cword.b.encdec) {
1199                                 cdata->cword.b.encdec=0;
1200                                 padlock_reload_key();
1201                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1202                                 cdata->cword.b.encdec=1;
1203                                 padlock_reload_key();
1204                                 while(nbytes) {
1205                                         unsigned char c = *(in_arg++);
1206                                         *(out_arg++) = c ^ *ivp;
1207                                         *(ivp++) = c, nbytes--;
1208                                 }
1209                         }
1210                         else {  padlock_reload_key();
1211                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1212                                 padlock_reload_key();
1213                                 while (nbytes) {
1214                                         *ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
1215                                         ivp++, nbytes--;
1216                                 }
1217                         }
1218                 }
1219
1220                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1221                 break;
1222
1223         case EVP_CIPH_OFB_MODE:
1224                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1225                 chunk &= ~(AES_BLOCK_SIZE-1);
1226                 if (chunk) do   {
1227                         if (inp_misaligned)
1228                                 inp = padlock_memcpy(out, in_arg, chunk);
1229                         else
1230                                 inp = in_arg;
1231                         in_arg += chunk;
1232
1233                         padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1234
1235                         if (out_misaligned)
1236                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1237                         else
1238                                 out     = out_arg+=chunk;
1239
1240                         nbytes -= chunk;
1241                         chunk   = PADLOCK_CHUNK;
1242                 } while (nbytes >= AES_BLOCK_SIZE);
1243
1244                 if (nbytes) {
1245                         unsigned char *ivp = cdata->iv;
1246
1247                         ctx->num = nbytes;
1248                         padlock_reload_key();   /* empirically found */
1249                         padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1250                         padlock_reload_key();   /* empirically found */
1251                         while (nbytes) {
1252                                 *(out_arg++) = *(in_arg++) ^ *ivp;
1253                                 ivp++, nbytes--;
1254                         }
1255                 }
1256
1257                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
1258                 break;
1259
1260         default:
1261                 return 0;
1262         }
1263
1264         /* Clean the realign buffer if it was used */
1265         if (out_misaligned) {
1266                 volatile unsigned long *p=(void *)out;
1267                 size_t   n = allocated/sizeof(*p);
1268                 while (n--) *p++=0;
1269         }
1270
1271         memset(cdata->iv, 0, AES_BLOCK_SIZE);
1272
1273         return 1;
1274 }
1275
1276 #endif /* OPENSSL_NO_AES */
1277
1278 /* ===== Random Number Generator ===== */
1279 /*
1280  * This code is not engaged. The reason is that it does not comply
1281  * with recommendations for VIA RNG usage for secure applications
1282  * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
1283  * provide meaningful error control...
1284  */
1285 /* Wrapper that provides an interface between the API and 
1286    the raw PadLock RNG */
1287 static int
1288 padlock_rand_bytes(unsigned char *output, int count)
1289 {
1290         unsigned int eax, buf;
1291
1292         while (count >= 8) {
1293                 eax = padlock_xstore(output, 0);
1294                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1295                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1296                 if (eax&(0x1F<<10))     return 0;
1297                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1298                 if ((eax&0x1F)!=8)      return 0; /* fatal failure...  */
1299                 output += 8;
1300                 count  -= 8;
1301         }
1302         while (count > 0) {
1303                 eax = padlock_xstore(&buf, 3);
1304                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1305                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1306                 if (eax&(0x1F<<10))     return 0;
1307                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1308                 if ((eax&0x1F)!=1)      return 0; /* fatal failure...  */
1309                 *output++ = (unsigned char)buf;
1310                 count--;
1311         }
1312         *(volatile unsigned int *)&buf=0;
1313
1314         return 1;
1315 }
1316
1317 /* Dummy but necessary function */
1318 static int
1319 padlock_rand_status(void)
1320 {
1321         return 1;
1322 }
1323
1324 /* Prepare structure for registration */
1325 static RAND_METHOD padlock_rand = {
1326         NULL,                   /* seed */
1327         padlock_rand_bytes,     /* bytes */
1328         NULL,                   /* cleanup */
1329         NULL,                   /* add */
1330         padlock_rand_bytes,     /* pseudorand */
1331         padlock_rand_status,    /* rand status */
1332 };
1333
1334 #else  /* !COMPILE_HW_PADLOCK */
1335 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1336 OPENSSL_EXPORT
1337 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
1338 OPENSSL_EXPORT
1339 int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; }
1340 IMPLEMENT_DYNAMIC_CHECK_FN()
1341 #endif
1342 #endif /* COMPILE_HW_PADLOCK */
1343
1344 #endif /* !OPENSSL_NO_HW_PADLOCK */
1345 #endif /* !OPENSSL_NO_HW */