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