Fix mingw warnings.
[openssl.git] / crypto / engine / eng_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__) && (defined(__i386__) || defined(__i386))) || \
105      (defined(_MSC_VER) && defined(_M_IX86))
106 #  define COMPILE_HW_PADLOCK
107 static ENGINE *ENGINE_padlock (void);
108 # endif
109 #endif
110
111 void ENGINE_load_padlock (void)
112 {
113 /* On non-x86 CPUs it just returns. */
114 #ifdef COMPILE_HW_PADLOCK
115         ENGINE *toadd = ENGINE_padlock ();
116         if (!toadd) return;
117         ENGINE_add (toadd);
118         ENGINE_free (toadd);
119         ERR_clear_error ();
120 #endif
121 }
122
123 #ifdef COMPILE_HW_PADLOCK
124 /* We do these includes here to avoid header problems on platforms that
125    do not have the VIA padlock anyway... */
126 #ifdef _WIN32
127 # include <malloc.h>
128 # ifndef alloca
129 #  define alloca _alloca
130 # endif
131 #else
132 # include <stdlib.h>
133 #endif
134
135 /* Function for ENGINE detection and control */
136 static int padlock_available(void);
137 static int padlock_init(ENGINE *e);
138
139 /* RNG Stuff */
140 static RAND_METHOD padlock_rand;
141
142 /* Cipher Stuff */
143 #ifndef OPENSSL_NO_AES
144 static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
145 #endif
146
147 /* Engine names */
148 static const char *padlock_id = "padlock";
149 static char padlock_name[100];
150
151 /* Available features */
152 static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
153 static int padlock_use_rng = 0; /* Random Number Generator */
154 #ifndef OPENSSL_NO_AES
155 static int padlock_aes_align_required = 1;
156 #endif
157
158 /* ===== Engine "management" functions ===== */
159
160 /* Prepare the ENGINE structure for registration */
161 static int
162 padlock_bind_helper(ENGINE *e)
163 {
164         /* Check available features */
165         padlock_available();
166
167 #if 1   /* disable RNG for now, see commentary in vicinity of RNG code */
168         padlock_use_rng=0;
169 #endif
170
171         /* Generate a nice engine name with available features */
172         BIO_snprintf(padlock_name, sizeof(padlock_name),
173                 "VIA PadLock (%s, %s)", 
174                  padlock_use_rng ? "RNG" : "no-RNG",
175                  padlock_use_ace ? "ACE" : "no-ACE");
176
177         /* Register everything or return with an error */ 
178         if (!ENGINE_set_id(e, padlock_id) ||
179             !ENGINE_set_name(e, padlock_name) ||
180
181             !ENGINE_set_init_function(e, padlock_init) ||
182 #ifndef OPENSSL_NO_AES
183             (padlock_use_ace && !ENGINE_set_ciphers (e, padlock_ciphers)) ||
184 #endif
185             (padlock_use_rng && !ENGINE_set_RAND (e, &padlock_rand))) {
186                 return 0;
187         }
188
189         /* Everything looks good */
190         return 1;
191 }
192
193 /* Constructor */
194 static ENGINE *
195 ENGINE_padlock(void)
196 {
197         ENGINE *eng = ENGINE_new();
198
199         if (!eng) {
200                 return NULL;
201         }
202
203         if (!padlock_bind_helper(eng)) {
204                 ENGINE_free(eng);
205                 return NULL;
206         }
207
208         return eng;
209 }
210
211 /* Check availability of the engine */
212 static int
213 padlock_init(ENGINE *e)
214 {
215         return (padlock_use_rng || padlock_use_ace);
216 }
217
218 /* This stuff is needed if this ENGINE is being compiled into a self-contained
219  * shared-library.
220  */
221 #ifdef DYNAMIC_ENGINE
222 static int
223 padlock_bind_fn(ENGINE *e, const char *id)
224 {
225         if (id && (strcmp(id, padlock_id) != 0)) {
226                 return 0;
227         }
228
229         if (!padlock_bind_helper(e))  {
230                 return 0;
231         }
232
233         return 1;
234 }
235
236 IMPLEMENT_DYNAMIC_CHECK_FN ();
237 IMPLEMENT_DYNAMIC_BIND_FN (padlock_bind_fn);
238 #endif /* DYNAMIC_ENGINE */
239
240 /* ===== Here comes the "real" engine ===== */
241
242 #ifndef OPENSSL_NO_AES
243 /* Some AES-related constants */
244 #define AES_BLOCK_SIZE          16
245 #define AES_KEY_SIZE_128        16
246 #define AES_KEY_SIZE_192        24
247 #define AES_KEY_SIZE_256        32
248
249 /* Here we store the status information relevant to the 
250    current context. */
251 /* BIG FAT WARNING:
252  *      Inline assembler in PADLOCK_XCRYPT_ASM()
253  *      depends on the order of items in this structure.
254  *      Don't blindly modify, reorder, etc!
255  */
256 struct padlock_cipher_data
257 {
258         unsigned char iv[AES_BLOCK_SIZE];       /* Initialization vector */
259         union { unsigned int pad[4];
260                 struct {
261                         int rounds:4;
262                         int dgst:1;     /* n/a in C3 */
263                         int align:1;    /* n/a in C3 */
264                         int ciphr:1;    /* n/a in C3 */
265                         unsigned int keygen:1;
266                         int interm:1;
267                         unsigned int encdec:1;
268                         int ksize:2;
269                 } b;
270         } cword;                /* Control word */
271         AES_KEY ks;             /* Encryption key */
272 };
273
274 /*
275  * Essentially this variable belongs in thread local storage.
276  * Having this variable global on the other hand can only cause
277  * few bogus key reloads [if any at all on single-CPU system],
278  * so we accept the penatly...
279  */
280 static volatile struct padlock_cipher_data *padlock_saved_context;
281 #endif
282
283 /*
284  * =======================================================
285  * Inline assembler section(s).
286  * =======================================================
287  * Order of arguments is chosen to facilitate Windows port
288  * using __fastcall calling convention. If you wish to add
289  * more routines, keep in mind that first __fastcall
290  * argument is passed in %ecx and second - in %edx.
291  * =======================================================
292  */
293 #if defined(__GNUC__) && __GNUC__>=2
294 /*
295  * As for excessive "push %ebx"/"pop %ebx" found all over.
296  * When generating position-independent code GCC won't let
297  * us use "b" in assembler templates nor even respect "ebx"
298  * in "clobber description." Therefore the trouble...
299  */
300
301 /* Helper function - check if a CPUID instruction
302    is available on this CPU */
303 static int
304 padlock_insn_cpuid_available(void)
305 {
306         int result = -1;
307
308         /* We're checking if the bit #21 of EFLAGS 
309            can be toggled. If yes = CPUID is available. */
310         asm volatile (
311                 "pushf\n"
312                 "popl %%eax\n"
313                 "xorl $0x200000, %%eax\n"
314                 "movl %%eax, %%ecx\n"
315                 "andl $0x200000, %%ecx\n"
316                 "pushl %%eax\n"
317                 "popf\n"
318                 "pushf\n"
319                 "popl %%eax\n"
320                 "andl $0x200000, %%eax\n"
321                 "xorl %%eax, %%ecx\n"
322                 "movl %%ecx, %0\n"
323                 : "=r" (result) : : "eax", "ecx");
324         
325         return (result == 0);
326 }
327
328 /* Load supported features of the CPU to see if
329    the PadLock is available. */
330 static int
331 padlock_available(void)
332 {
333         char vendor_string[16];
334         unsigned int eax, edx;
335
336         /* First check if the CPUID instruction is available at all... */
337         if (! padlock_insn_cpuid_available())
338                 return 0;
339
340         /* Are we running on the Centaur (VIA) CPU? */
341         eax = 0x00000000;
342         vendor_string[12] = 0;
343         asm volatile (
344                 "pushl  %%ebx\n"
345                 "cpuid\n"
346                 "movl   %%ebx,(%%edi)\n"
347                 "movl   %%edx,4(%%edi)\n"
348                 "movl   %%ecx,8(%%edi)\n"
349                 "popl   %%ebx"
350                 : "+a"(eax) : "D"(vendor_string) : "ecx", "edx");
351         if (strcmp(vendor_string, "CentaurHauls") != 0)
352                 return 0;
353
354         /* Check for Centaur Extended Feature Flags presence */
355         eax = 0xC0000000;
356         asm volatile ("pushl %%ebx; cpuid; popl %%ebx"
357                 : "+a"(eax) : : "ecx", "edx");
358         if (eax < 0xC0000001)
359                 return 0;
360
361         /* Read the Centaur Extended Feature Flags */
362         eax = 0xC0000001;
363         asm volatile ("pushl %%ebx; cpuid; popl %%ebx"
364                 : "+a"(eax), "=d"(edx) : : "ecx");
365
366         /* Fill up some flags */
367         padlock_use_ace = ((edx & (0x3<<6)) == (0x3<<6));
368         padlock_use_rng = ((edx & (0x3<<2)) == (0x3<<2));
369
370         return padlock_use_ace + padlock_use_rng;
371 }
372
373 #ifndef OPENSSL_NO_AES
374 /* Our own htonl()/ntohl() */
375 static inline void
376 padlock_bswapl(AES_KEY *ks)
377 {
378         size_t i = sizeof(ks->rd_key)/sizeof(ks->rd_key[0]);
379         unsigned int *key = ks->rd_key;
380
381         while (i--) {
382                 asm volatile ("bswapl %0" : "+r"(*key));
383                 key++;
384         }
385 }
386 #endif
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), "m"(*cdata)  \
442                 : "edx", "cc", "memory");       \
443         return iv;                              \
444 }
445
446 /* Generate all functions with appropriate opcodes */
447 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb, ".byte 0xf3,0x0f,0xa7,0xc8")     /* rep xcryptecb */
448 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc, ".byte 0xf3,0x0f,0xa7,0xd0")     /* rep xcryptcbc */
449 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb, ".byte 0xf3,0x0f,0xa7,0xe0")     /* rep xcryptcfb */
450 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb, ".byte 0xf3,0x0f,0xa7,0xe8")     /* rep xcryptofb */
451 #endif
452
453 /* The RNG call itself */
454 static inline unsigned int
455 padlock_xstore(void *addr, unsigned int edx_in)
456 {
457         unsigned int eax_out;
458
459         asm volatile (".byte 0x0f,0xa7,0xc0"    /* xstore */
460             : "=a"(eax_out),"=m"(*(unsigned *)addr)
461             : "D"(addr), "d" (edx_in)
462             );
463
464         return eax_out;
465 }
466
467 /* Why not inline 'rep movsd'? I failed to find information on what
468  * value in Direction Flag one can expect and consequently have to
469  * apply "better-safe-than-sorry" approach and assume "undefined."
470  * I could explicitly clear it and restore the original value upon
471  * return from padlock_aes_cipher, but it's presumably too much
472  * trouble for too little gain...
473  *
474  * In case you wonder 'rep xcrypt*' instructions above are *not*
475  * affected by the Direction Flag and pointers advance toward
476  * larger addresses unconditionally.
477  */ 
478 static inline unsigned char *
479 padlock_memcpy(void *dst,const void *src,size_t n)
480 {
481         long       *d=dst;
482         const long *s=src;
483
484         n /= sizeof(*d);
485         do { *d++ = *s++; } while (--n);
486
487         return dst;
488 }
489
490 #elif defined(_MSC_VER)
491 /*
492  * Unlike GCC these are real functions. In order to minimize impact
493  * on performance we adhere to __fastcall calling convention in
494  * order to get two first arguments passed through %ecx and %edx.
495  * Which kind of suits very well, as instructions in question use
496  * both %ecx and %edx as input:-)
497  */
498 #define REP_XCRYPT(code)                \
499         _asm _emit 0xf3                 \
500         _asm _emit 0x0f _asm _emit 0xa7 \
501         _asm _emit code
502
503 /* BIG FAT WARNING: 
504  *      The offsets used with 'lea' instructions
505  *      describe items of the 'padlock_cipher_data'
506  *      structure.
507  */
508 #define PADLOCK_XCRYPT_ASM(name,code)   \
509 static void * __fastcall                \
510         name (size_t cnt, void *cdata,  \
511         void *outp, const void *inp)    \
512 {       _asm    mov     eax,edx         \
513         _asm    lea     edx,[eax+16]    \
514         _asm    lea     ebx,[eax+32]    \
515         _asm    mov     edi,outp        \
516         _asm    mov     esi,inp         \
517         REP_XCRYPT(code)                \
518 }
519
520 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb,0xc8)
521 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc,0xd0)
522 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb,0xe0)
523 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb,0xe8)
524
525 static int __fastcall
526 padlock_xstore(void *outp,unsigned int code)
527 {       _asm    mov     edi,ecx
528         _asm _emit 0x0f _asm _emit 0xa7 _asm _emit 0xc0
529 }
530
531 static void __fastcall
532 padlock_reload_key(void)
533 {       _asm pushfd _asm popfd          }
534
535 static void __fastcall
536 padlock_verify_context(void *cdata)
537 {       _asm    {
538                 pushfd
539                 bt      DWORD PTR[esp],30
540                 jnc     skip
541                 cmp     ecx,padlock_saved_context
542                 je      skip
543                 popfd
544                 sub     esp,4
545         skip:   add     esp,4
546                 mov     padlock_saved_context,ecx
547                 }
548 }
549
550 static int
551 padlock_available(void)
552 {       _asm    {
553                 pushfd
554                 pop     eax
555                 mov     ecx,eax
556                 xor     eax,1<<21
557                 push    eax
558                 popfd
559                 pushfd
560                 pop     eax
561                 xor     eax,ecx
562                 bt      eax,21
563                 jnc     noluck
564                 mov     eax,0
565                 cpuid
566                 xor     eax,eax
567                 cmp     ebx,'tneC'
568                 jne     noluck
569                 cmp     edx,'Hrua'
570                 jne     noluck
571                 cmp     ecx,'slua'
572                 jne     noluck
573                 mov     eax,0xC0000000
574                 cpuid
575                 mov     edx,eax
576                 xor     eax,eax
577                 cmp     edx,0xC0000001
578                 jb      noluck
579                 mov     eax,0xC0000001
580                 cpuid
581                 xor     eax,eax
582                 bt      edx,6
583                 jnc     skip_a
584                 bt      edx,7
585                 jnc     skip_a
586                 mov     padlock_use_ace,1
587                 inc     eax
588         skip_a: bt      edx,2
589                 jnc     skip_r
590                 bt      edx,3
591                 jnc     skip_r
592                 mov     padlock_use_rng,1
593                 inc     eax
594         skip_r:
595         noluck:
596                 }
597 }
598
599 static void __fastcall
600 padlock_bswapl(void *key)
601 {       _asm    {
602                 pushfd
603                 cld
604                 mov     esi,ecx
605                 mov     edi,ecx
606                 mov     ecx,60
607         up:     lodsd
608                 bswap   eax
609                 stosd
610                 loop    up
611                 popfd
612                 }
613 }
614
615 /* MS actually specifies status of Direction Flag and compiler even
616  * manages to compile following as 'rep movsd' all by itself...
617  */
618 #define padlock_memcpy(o,i,n) ((unsigned char *)memcpy((o),(i),(n)&~3U))
619 #endif
620
621 /* ===== AES encryption/decryption ===== */
622 #ifndef OPENSSL_NO_AES
623
624 #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
625 #define NID_aes_128_cfb NID_aes_128_cfb128
626 #endif
627
628 #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
629 #define NID_aes_128_ofb NID_aes_128_ofb128
630 #endif
631
632 #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
633 #define NID_aes_192_cfb NID_aes_192_cfb128
634 #endif
635
636 #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
637 #define NID_aes_192_ofb NID_aes_192_ofb128
638 #endif
639
640 #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
641 #define NID_aes_256_cfb NID_aes_256_cfb128
642 #endif
643
644 #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
645 #define NID_aes_256_ofb NID_aes_256_ofb128
646 #endif
647
648 /* List of supported ciphers. */
649 static int padlock_cipher_nids[] = {
650         NID_aes_128_ecb,
651         NID_aes_128_cbc,
652         NID_aes_128_cfb,
653         NID_aes_128_ofb,
654
655         NID_aes_192_ecb,
656         NID_aes_192_cbc,
657         NID_aes_192_cfb,
658         NID_aes_192_ofb,
659
660         NID_aes_256_ecb,
661         NID_aes_256_cbc,
662         NID_aes_256_cfb,
663         NID_aes_256_ofb,
664 };
665 static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/
666                                       sizeof(padlock_cipher_nids[0]));
667
668 /* Function prototypes ... */
669 static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
670                                 const unsigned char *iv, int enc);
671 static int padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
672                               const unsigned char *in, size_t nbytes);
673
674 #define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) +         \
675         ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
676 #define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
677         NEAREST_ALIGNED(ctx->cipher_data))
678
679 #define EVP_CIPHER_block_size_ECB       AES_BLOCK_SIZE
680 #define EVP_CIPHER_block_size_CBC       AES_BLOCK_SIZE
681 #define EVP_CIPHER_block_size_OFB       1
682 #define EVP_CIPHER_block_size_CFB       1
683
684 /* Declaring so many ciphers by hand would be a pain.
685    Instead introduce a bit of preprocessor magic :-) */
686 #define DECLARE_AES_EVP(ksize,lmode,umode)      \
687 static const EVP_CIPHER padlock_aes_##ksize##_##lmode = {       \
688         NID_aes_##ksize##_##lmode,              \
689         EVP_CIPHER_block_size_##umode,  \
690         AES_KEY_SIZE_##ksize,           \
691         AES_BLOCK_SIZE,                 \
692         0 | EVP_CIPH_##umode##_MODE,    \
693         padlock_aes_init_key,           \
694         padlock_aes_cipher,             \
695         NULL,                           \
696         sizeof(struct padlock_cipher_data) + 16,        \
697         EVP_CIPHER_set_asn1_iv,         \
698         EVP_CIPHER_get_asn1_iv,         \
699         NULL,                           \
700         NULL                            \
701 }
702
703 DECLARE_AES_EVP(128,ecb,ECB);
704 DECLARE_AES_EVP(128,cbc,CBC);
705 DECLARE_AES_EVP(128,cfb,CFB);
706 DECLARE_AES_EVP(128,ofb,OFB);
707
708 DECLARE_AES_EVP(192,ecb,ECB);
709 DECLARE_AES_EVP(192,cbc,CBC);
710 DECLARE_AES_EVP(192,cfb,CFB);
711 DECLARE_AES_EVP(192,ofb,OFB);
712
713 DECLARE_AES_EVP(256,ecb,ECB);
714 DECLARE_AES_EVP(256,cbc,CBC);
715 DECLARE_AES_EVP(256,cfb,CFB);
716 DECLARE_AES_EVP(256,ofb,OFB);
717
718 static int
719 padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
720 {
721         /* No specific cipher => return a list of supported nids ... */
722         if (!cipher) {
723                 *nids = padlock_cipher_nids;
724                 return padlock_cipher_nids_num;
725         }
726
727         /* ... or the requested "cipher" otherwise */
728         switch (nid) {
729           case NID_aes_128_ecb:
730             *cipher = &padlock_aes_128_ecb;
731             break;
732           case NID_aes_128_cbc:
733             *cipher = &padlock_aes_128_cbc;
734             break;
735           case NID_aes_128_cfb:
736             *cipher = &padlock_aes_128_cfb;
737             break;
738           case NID_aes_128_ofb:
739             *cipher = &padlock_aes_128_ofb;
740             break;
741
742           case NID_aes_192_ecb:
743             *cipher = &padlock_aes_192_ecb;
744             break;
745           case NID_aes_192_cbc:
746             *cipher = &padlock_aes_192_cbc;
747             break;
748           case NID_aes_192_cfb:
749             *cipher = &padlock_aes_192_cfb;
750             break;
751           case NID_aes_192_ofb:
752             *cipher = &padlock_aes_192_ofb;
753             break;
754
755           case NID_aes_256_ecb:
756             *cipher = &padlock_aes_256_ecb;
757             break;
758           case NID_aes_256_cbc:
759             *cipher = &padlock_aes_256_cbc;
760             break;
761           case NID_aes_256_cfb:
762             *cipher = &padlock_aes_256_cfb;
763             break;
764           case NID_aes_256_ofb:
765             *cipher = &padlock_aes_256_ofb;
766             break;
767
768           default:
769             /* Sorry, we don't support this NID */
770             *cipher = NULL;
771             return 0;
772         }
773
774         return 1;
775 }
776
777 /* Prepare the encryption key for PadLock usage */
778 static int
779 padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key,
780                       const unsigned char *iv, int enc)
781 {
782         struct padlock_cipher_data *cdata;
783         int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
784
785         if (key==NULL) return 0;        /* ERROR */
786
787         cdata = ALIGNED_CIPHER_DATA(ctx);
788         memset(cdata, 0, sizeof(struct padlock_cipher_data));
789
790         /* Prepare Control word. */
791         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE)
792                 cdata->cword.b.encdec = 0;
793         else
794                 cdata->cword.b.encdec = (ctx->encrypt == 0);
795         cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
796         cdata->cword.b.ksize = (key_len - 128) / 64;
797
798         switch(key_len) {
799                 case 128:
800                         /* PadLock can generate an extended key for
801                            AES128 in hardware */
802                         memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
803                         cdata->cword.b.keygen = 0;
804                         break;
805
806                 case 192:
807                 case 256:
808                         /* Generate an extended AES key in software.
809                            Needed for AES192/AES256 */
810                         /* Well, the above applies to Stepping 8 CPUs
811                            and is listed as hardware errata. They most
812                            likely will fix it at some point and then
813                            a check for stepping would be due here. */
814                         if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE ||
815                             EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE ||
816                             enc)
817                                 AES_set_encrypt_key(key, key_len, &cdata->ks);
818                         else
819                                 AES_set_decrypt_key(key, key_len, &cdata->ks);
820 #ifndef AES_ASM
821                         /* OpenSSL C functions use byte-swapped extended key. */
822                         padlock_bswapl(&cdata->ks);
823 #endif
824                         cdata->cword.b.keygen = 1;
825                         break;
826
827                 default:
828                         /* ERROR */
829                         return 0;
830         }
831
832         /*
833          * This is done to cover for cases when user reuses the
834          * context for new key. The catch is that if we don't do
835          * this, padlock_eas_cipher might proceed with old key...
836          */
837         padlock_reload_key ();
838
839         return 1;
840 }
841
842 /* 
843  * Simplified version of padlock_aes_cipher() used when
844  * 1) both input and output buffers are at aligned addresses.
845  * or when
846  * 2) running on a newer CPU that doesn't require aligned buffers.
847  */
848 static int
849 padlock_aes_cipher_omnivorous(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
850                 const unsigned char *in_arg, size_t nbytes)
851 {
852         struct padlock_cipher_data *cdata;
853         void  *iv;
854
855         cdata = ALIGNED_CIPHER_DATA(ctx);
856         padlock_verify_context(cdata);
857
858         switch (EVP_CIPHER_CTX_mode(ctx)) {
859         case EVP_CIPH_ECB_MODE:
860                 padlock_xcrypt_ecb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
861                 break;
862
863         case EVP_CIPH_CBC_MODE:
864                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
865                 iv = padlock_xcrypt_cbc(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
866                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
867                 break;
868
869         case EVP_CIPH_CFB_MODE:
870                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
871                 iv = padlock_xcrypt_cfb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
872                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
873                 break;
874
875         case EVP_CIPH_OFB_MODE:
876                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
877                 padlock_xcrypt_ofb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
878                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
879                 break;
880
881         default:
882                 return 0;
883         }
884
885         memset(cdata->iv, 0, AES_BLOCK_SIZE);
886
887         return 1;
888 }
889
890 #ifndef  PADLOCK_CHUNK
891 # define PADLOCK_CHUNK  512     /* Must be a power of 2 larger than 16 */
892 #endif
893 #if PADLOCK_CHUNK<16 || PADLOCK_CHUNK&(PADLOCK_CHUNK-1)
894 # error "insane PADLOCK_CHUNK..."
895 #endif
896
897 /* Re-align the arguments to 16-Bytes boundaries and run the 
898    encryption function itself. This function is not AES-specific. */
899 static int
900 padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
901                    const unsigned char *in_arg, size_t nbytes)
902 {
903         struct padlock_cipher_data *cdata;
904         const  void *inp;
905         unsigned char  *out;
906         void  *iv;
907         int    inp_misaligned, out_misaligned, realign_in_loop;
908         size_t chunk, allocated=0;
909
910         /* ctx->num is maintained in byte-oriented modes,
911            such as CFB and OFB... */
912         if ((chunk = ctx->num)) { /* borrow chunk variable */
913                 unsigned char *ivp=ctx->iv;
914
915                 switch (EVP_CIPHER_CTX_mode(ctx)) {
916                 case EVP_CIPH_CFB_MODE:
917                         if (chunk >= AES_BLOCK_SIZE)
918                                 return 0; /* bogus value */
919
920                         if (ctx->encrypt)
921                                 while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
922                                         ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
923                                         chunk++, nbytes--;
924                                 }
925                         else    while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
926                                         unsigned char c = *(in_arg++);
927                                         *(out_arg++) = c ^ ivp[chunk];
928                                         ivp[chunk++] = c, nbytes--;
929                                 }
930
931                         ctx->num = chunk%AES_BLOCK_SIZE;
932                         break;
933                 case EVP_CIPH_OFB_MODE:
934                         if (chunk >= AES_BLOCK_SIZE)
935                                 return 0; /* bogus value */
936
937                         while (chunk<AES_BLOCK_SIZE && nbytes!=0) {
938                                 *(out_arg++) = *(in_arg++) ^ ivp[chunk];
939                                 chunk++, nbytes--;
940                         }
941
942                         ctx->num = chunk%AES_BLOCK_SIZE;
943                         break;
944                 }
945         }
946
947         if (nbytes == 0)
948                 return 1;
949 #if 0
950         if (nbytes % AES_BLOCK_SIZE)
951                 return 0; /* are we expected to do tail processing? */
952 #else
953         /* nbytes is always multiple of AES_BLOCK_SIZE in ECB and CBC
954            modes and arbitrary value in byte-oriented modes, such as
955            CFB and OFB... */
956 #endif
957
958         /* VIA promises CPUs that won't require alignment in the future.
959            For now padlock_aes_align_required is initialized to 1 and
960            the condition is never met... */
961         /* C7 core is capable to manage unaligned input in non-ECB[!]
962            mode, but performance penalties appear to be approximately
963            same as for software alignment below or ~3x. They promise to
964            improve it in the future, but for now we can just as well
965            pretend that it can only handle aligned input... */
966         if (!padlock_aes_align_required && (nbytes%AES_BLOCK_SIZE)==0)
967                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
968
969         inp_misaligned = (((size_t)in_arg) & 0x0F);
970         out_misaligned = (((size_t)out_arg) & 0x0F);
971
972         /* Note that even if output is aligned and input not,
973          * I still prefer to loop instead of copy the whole
974          * input and then encrypt in one stroke. This is done
975          * in order to improve L1 cache utilization... */
976         realign_in_loop = out_misaligned|inp_misaligned;
977
978         if (!realign_in_loop && (nbytes%AES_BLOCK_SIZE)==0)
979                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
980
981         /* this takes one "if" out of the loops */
982         chunk  = nbytes;
983         chunk %= PADLOCK_CHUNK;
984         if (chunk==0) chunk = PADLOCK_CHUNK;
985
986         if (out_misaligned) {
987                 /* optmize for small input */
988                 allocated = (chunk<nbytes?PADLOCK_CHUNK:nbytes);
989                 out = alloca(0x10 + allocated);
990                 out = NEAREST_ALIGNED(out);
991         }
992         else
993                 out = out_arg;
994
995         cdata = ALIGNED_CIPHER_DATA(ctx);
996         padlock_verify_context(cdata);
997
998         switch (EVP_CIPHER_CTX_mode(ctx)) {
999         case EVP_CIPH_ECB_MODE:
1000                 do      {
1001                         if (inp_misaligned)
1002                                 inp = padlock_memcpy(out, in_arg, chunk);
1003                         else
1004                                 inp = in_arg;
1005                         in_arg += chunk;
1006
1007                         padlock_xcrypt_ecb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1008
1009                         if (out_misaligned)
1010                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1011                         else
1012                                 out     = out_arg+=chunk;
1013
1014                         nbytes -= chunk;
1015                         chunk   = PADLOCK_CHUNK;
1016                 } while (nbytes);
1017                 break;
1018
1019         case EVP_CIPH_CBC_MODE:
1020                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1021                 goto cbc_shortcut;
1022                 do      {
1023                         if (iv != cdata->iv)
1024                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1025                         chunk = PADLOCK_CHUNK;
1026                 cbc_shortcut: /* optimize for small input */
1027                         if (inp_misaligned)
1028                                 inp = padlock_memcpy(out, in_arg, chunk);
1029                         else
1030                                 inp = in_arg;
1031                         in_arg += chunk;
1032
1033                         iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1034
1035                         if (out_misaligned)
1036                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1037                         else
1038                                 out     = out_arg+=chunk;
1039
1040                 } while (nbytes -= chunk);
1041                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1042                 break;
1043
1044         case EVP_CIPH_CFB_MODE:
1045                 memcpy (iv = cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1046                 chunk &= ~(AES_BLOCK_SIZE-1);
1047                 if (chunk)      goto cfb_shortcut;
1048                 else            goto cfb_skiploop;
1049                 do      {
1050                         if (iv != cdata->iv)
1051                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
1052                         chunk = PADLOCK_CHUNK;
1053                 cfb_shortcut: /* optimize for small input */
1054                         if (inp_misaligned)
1055                                 inp = padlock_memcpy(out, in_arg, chunk);
1056                         else
1057                                 inp = in_arg;
1058                         in_arg += chunk;
1059
1060                         iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1061
1062                         if (out_misaligned)
1063                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1064                         else
1065                                 out     = out_arg+=chunk;
1066
1067                         nbytes -= chunk;
1068                 } while (nbytes >= AES_BLOCK_SIZE);
1069
1070                 cfb_skiploop:
1071                 if (nbytes) {
1072                         unsigned char *ivp = cdata->iv;
1073
1074                         if (iv != ivp) {
1075                                 memcpy(ivp, iv, AES_BLOCK_SIZE);
1076                                 iv = ivp;
1077                         }
1078                         ctx->num = nbytes;
1079                         if (cdata->cword.b.encdec) {
1080                                 cdata->cword.b.encdec=0;
1081                                 padlock_reload_key();
1082                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1083                                 cdata->cword.b.encdec=1;
1084                                 padlock_reload_key();
1085                                 while(nbytes) {
1086                                         unsigned char c = *(in_arg++);
1087                                         *(out_arg++) = c ^ *ivp;
1088                                         *(ivp++) = c, nbytes--;
1089                                 }
1090                         }
1091                         else {  padlock_reload_key();
1092                                 padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1093                                 padlock_reload_key();
1094                                 while (nbytes) {
1095                                         *ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
1096                                         ivp++, nbytes--;
1097                                 }
1098                         }
1099                 }
1100
1101                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
1102                 break;
1103
1104         case EVP_CIPH_OFB_MODE:
1105                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
1106                 chunk &= ~(AES_BLOCK_SIZE-1);
1107                 if (chunk) do   {
1108                         if (inp_misaligned)
1109                                 inp = padlock_memcpy(out, in_arg, chunk);
1110                         else
1111                                 inp = in_arg;
1112                         in_arg += chunk;
1113
1114                         padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
1115
1116                         if (out_misaligned)
1117                                 out_arg = padlock_memcpy(out_arg, out, chunk) + chunk;
1118                         else
1119                                 out     = out_arg+=chunk;
1120
1121                         nbytes -= chunk;
1122                         chunk   = PADLOCK_CHUNK;
1123                 } while (nbytes >= AES_BLOCK_SIZE);
1124
1125                 if (nbytes) {
1126                         unsigned char *ivp = cdata->iv;
1127
1128                         ctx->num = nbytes;
1129                         padlock_reload_key();   /* empirically found */
1130                         padlock_xcrypt_ecb(1,cdata,ivp,ivp);
1131                         padlock_reload_key();   /* empirically found */
1132                         while (nbytes) {
1133                                 *(out_arg++) = *(in_arg++) ^ *ivp;
1134                                 ivp++, nbytes--;
1135                         }
1136                 }
1137
1138                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
1139                 break;
1140
1141         default:
1142                 return 0;
1143         }
1144
1145         /* Clean the realign buffer if it was used */
1146         if (out_misaligned) {
1147                 volatile unsigned long *p=(void *)out;
1148                 size_t   n = allocated/sizeof(*p);
1149                 while (n--) *p++=0;
1150         }
1151
1152         memset(cdata->iv, 0, AES_BLOCK_SIZE);
1153
1154         return 1;
1155 }
1156
1157 #endif /* OPENSSL_NO_AES */
1158
1159 /* ===== Random Number Generator ===== */
1160 /*
1161  * This code is not engaged. The reason is that it does not comply
1162  * with recommendations for VIA RNG usage for secure applications
1163  * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
1164  * provide meaningful error control...
1165  */
1166 /* Wrapper that provides an interface between the API and 
1167    the raw PadLock RNG */
1168 static int
1169 padlock_rand_bytes(unsigned char *output, int count)
1170 {
1171         unsigned int eax, buf;
1172
1173         while (count >= 8) {
1174                 eax = padlock_xstore(output, 0);
1175                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1176                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1177                 if (eax&(0x1F<<10))     return 0;
1178                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1179                 if ((eax&0x1F)!=8)      return 0; /* fatal failure...  */
1180                 output += 8;
1181                 count  -= 8;
1182         }
1183         while (count > 0) {
1184                 eax = padlock_xstore(&buf, 3);
1185                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1186                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1187                 if (eax&(0x1F<<10))     return 0;
1188                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1189                 if ((eax&0x1F)!=1)      return 0; /* fatal failure...  */
1190                 *output++ = (unsigned char)buf;
1191                 count--;
1192         }
1193         *(volatile unsigned int *)&buf=0;
1194
1195         return 1;
1196 }
1197
1198 /* Dummy but necessary function */
1199 static int
1200 padlock_rand_status(void)
1201 {
1202         return 1;
1203 }
1204
1205 /* Prepare structure for registration */
1206 static RAND_METHOD padlock_rand = {
1207         NULL,                   /* seed */
1208         padlock_rand_bytes,     /* bytes */
1209         NULL,                   /* cleanup */
1210         NULL,                   /* add */
1211         padlock_rand_bytes,     /* pseudorand */
1212         padlock_rand_status,    /* rand status */
1213 };
1214
1215 #endif /* COMPILE_HW_PADLOCK */
1216
1217 #endif /* !OPENSSL_NO_HW_PADLOCK */
1218 #endif /* !OPENSSL_NO_HW */