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