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