Padlock engine update to fix a typo in MSC assembler and to address
[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 # endif
107 #endif
108
109 static ENGINE *ENGINE_padlock (void);
110
111 void ENGINE_load_padlock (void)
112 {
113 /* On non-x86 CPUs it just returns. */
114 #ifdef COMPILE_HW_PADLOCK
115         ENGINE *toadd = ENGINE_padlock ();
116         if (!toadd) return;
117         ENGINE_add (toadd);
118         ENGINE_free (toadd);
119         ERR_clear_error ();
120 #endif
121 }
122
123 #ifdef COMPILE_HW_PADLOCK
124 /* Function for ENGINE detection and control */
125 static int padlock_available(void);
126 static int padlock_init(ENGINE *e);
127
128 /* RNG Stuff */
129 static RAND_METHOD padlock_rand;
130
131 /* Cipher Stuff */
132 static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
133
134 /* Engine names */
135 static const char *padlock_id = "padlock";
136 static char padlock_name[100];
137
138 /* Available features */
139 static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
140 static int padlock_use_rng = 0; /* Random Number Generator */
141 static int padlock_aes_align_required = 1;
142
143 /* ===== Engine "management" functions ===== */
144
145 /* Prepare the ENGINE structure for registration */
146 static int
147 padlock_bind_helper(ENGINE *e)
148 {
149         /* Check available features */
150         padlock_available();
151
152 #if 1   /* disable RNG for now, see commentary in vicinity of RNG code */
153         padlock_use_rng=0;
154 #endif
155
156         /* Generate a nice engine name with available features */
157         snprintf(padlock_name, sizeof(padlock_name), "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 #elif defined(_MSC_VER)
443 /*
444  * Unlike GCC these are real functions. In order to minimize impact
445  * on performance we adhere to __fastcall calling convention in
446  * order to get two first arguments passed through %ecx and %edx.
447  * Which kind of suits very well, as instructions in question use
448  * both %ecx and %edx as input:-)
449  */
450 #define REP_XCRYPT(code)                \
451         _asm _emit 0xf3                 \
452         _asm _emit 0x0f _asm _emit 0xa7 \
453         _asm _emit code
454
455 /* BIG FAT WARNING: 
456  *      The offsets used with 'lea' instructions
457  *      describe items of the 'padlock_cipher_data'
458  *      structure.
459  */
460 #define PADLOCK_XCRYPT_ASM(name,code)   \
461 static void * __fastcall                \
462         name (size_t cnt, void *cdata,  \
463         void *outp, const void *inp)    \
464 {       _asm    mov     eax,edx         \
465         _asm    lea     edx,[eax+16]    \
466         _asm    lea     ebx,[eax+32]    \
467         _asm    mov     edi,outp        \
468         _asm    mov     esi,inp         \
469         REP_XCRYPT(code)                \
470 }
471
472 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ecb,0xc8)
473 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cbc,0xd0)
474 PADLOCK_XCRYPT_ASM(padlock_xcrypt_cfb,0xe0)
475 PADLOCK_XCRYPT_ASM(padlock_xcrypt_ofb,0xe8)
476
477 static int __fastcall
478 padlock_xstore(void *outp,unsigned int code)
479 {       _asm    mov     edi,ecx
480         _asm _emit 0x0f _asm _emit 0xa7 _asm _emit 0xc0
481 }
482
483 static void __fastcall
484 padlock_reload_key(void)
485 {       _asm pushfd _asm popfd          }
486
487 static void __fastcall
488 padlock_verify_context(void *cdata)
489 {       _asm    {
490                 pushfd
491                 bt      DWORD PTR[esp],30
492                 jnc     skip
493                 cmp     ecx,padlock_saved_context
494                 je      skip
495                 mov     padlock_saved_context,ecx
496                 popfd
497                 sub     esp,4
498         skip:   add     esp,4
499                 }
500 }
501
502 static int
503 padlock_available(void)
504 {       _asm    {
505                 pushfd
506                 pop     eax
507                 mov     ecx,eax
508                 xor     eax,1<<21
509                 push    eax
510                 popfd
511                 pushfd
512                 pop     eax
513                 xor     eax,ecx
514                 bt      eax,21
515                 jnc     noluck
516                 mov     eax,0
517                 cpuid
518                 xor     eax,eax
519                 cmp     ebx,'tneC'
520                 jne     noluck
521                 cmp     edx,'Hrua'
522                 jne     noluck
523                 cmp     ecx,'slua'
524                 jne     noluck
525                 mov     eax,0xC0000000
526                 cpuid
527                 mov     edx,eax
528                 xor     eax,eax
529                 cmp     edx,0xC0000001
530                 jb      noluck
531                 mov     eax,0xC0000001
532                 cpuid
533                 xor     eax,eax
534                 bt      edx,6
535                 jnc     skip_a
536                 bt      edx,7
537                 jnc     skip_a
538                 mov     padlock_use_ace,1
539                 inc     eax
540         skip_a: bt      edx,2
541                 jnc     skip_r
542                 bt      edx,3
543                 jnc     skip_r
544                 mov     padlock_use_rng,1
545                 inc     eax
546         skip_r:
547         noluck:
548                 }
549 }
550
551 static void __fastcall
552 padlock_bswapl(void *key)
553 {       _asm    {
554                 pushfd
555                 cld
556                 mov     esi,ecx
557                 mov     edi,ecx
558                 mov     ecx,60
559         up:     lodsd
560                 bswap   eax
561                 stosd
562                 loop    up
563                 popfd
564                 }
565 }
566 #endif
567
568 /* ===== AES encryption/decryption ===== */
569
570 #if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
571 #define NID_aes_128_cfb NID_aes_128_cfb128
572 #endif
573
574 #if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
575 #define NID_aes_128_ofb NID_aes_128_ofb128
576 #endif
577
578 #if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
579 #define NID_aes_192_cfb NID_aes_192_cfb128
580 #endif
581
582 #if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
583 #define NID_aes_192_ofb NID_aes_192_ofb128
584 #endif
585
586 #if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
587 #define NID_aes_256_cfb NID_aes_256_cfb128
588 #endif
589
590 #if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
591 #define NID_aes_256_ofb NID_aes_256_ofb128
592 #endif
593
594 /* List of supported ciphers. */
595 static int padlock_cipher_nids[] = {
596         NID_aes_128_ecb,
597         NID_aes_128_cbc,
598         NID_aes_128_cfb,
599         NID_aes_128_ofb,
600
601         NID_aes_192_ecb,
602         NID_aes_192_cbc,
603 //      NID_aes_192_cfb,        /* FIXME: AES192/256 CFB/OFB don't work. */
604 //      NID_aes_192_ofb,
605
606         NID_aes_256_ecb,
607         NID_aes_256_cbc,
608 //      NID_aes_256_cfb,
609 //      NID_aes_256_ofb,
610 };
611 static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids)/
612                                       sizeof(padlock_cipher_nids[0]));
613
614 /* Function prototypes ... */
615 static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
616                                 const unsigned char *iv, int enc);
617 static int padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
618                               const unsigned char *in, unsigned int nbytes);
619
620 #define NEAREST_ALIGNED(ptr) ( (char *)(ptr) +          \
621         ( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F )      )
622 #define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
623         NEAREST_ALIGNED(ctx->cipher_data))
624
625 /* Declaring so many ciphers by hand would be a pain.
626    Instead introduce a bit of preprocessor magic :-) */
627 #define DECLARE_AES_EVP(ksize,lmode,umode)      \
628 static const EVP_CIPHER padlock_aes_##ksize##_##lmode = {       \
629         NID_aes_##ksize##_##lmode,              \
630         AES_BLOCK_SIZE,                 \
631         AES_KEY_SIZE_##ksize,           \
632         AES_BLOCK_SIZE,                 \
633         0 | EVP_CIPH_##umode##_MODE,    \
634         padlock_aes_init_key,           \
635         padlock_aes_cipher,             \
636         NULL,                           \
637         sizeof(struct padlock_cipher_data) + 16,        \
638         EVP_CIPHER_set_asn1_iv,         \
639         EVP_CIPHER_get_asn1_iv,         \
640         NULL,                           \
641         NULL                            \
642 }
643
644 DECLARE_AES_EVP(128,ecb,ECB);
645 DECLARE_AES_EVP(128,cbc,CBC);
646 DECLARE_AES_EVP(128,cfb,CFB);
647 DECLARE_AES_EVP(128,ofb,OFB);
648
649 DECLARE_AES_EVP(192,ecb,ECB);
650 DECLARE_AES_EVP(192,cbc,CBC);
651 DECLARE_AES_EVP(192,cfb,CFB);
652 DECLARE_AES_EVP(192,ofb,OFB);
653
654 DECLARE_AES_EVP(256,ecb,ECB);
655 DECLARE_AES_EVP(256,cbc,CBC);
656 DECLARE_AES_EVP(256,cfb,CFB);
657 DECLARE_AES_EVP(256,ofb,OFB);
658
659 static int
660 padlock_ciphers (ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
661 {
662         /* No specific cipher => return a list of supported nids ... */
663         if (!cipher) {
664                 *nids = padlock_cipher_nids;
665                 return padlock_cipher_nids_num;
666         }
667
668         /* ... or the requested "cipher" otherwise */
669         switch (nid) {
670           case NID_aes_128_ecb:
671             *cipher = &padlock_aes_128_ecb;
672             break;
673           case NID_aes_128_cbc:
674             *cipher = &padlock_aes_128_cbc;
675             break;
676           case NID_aes_128_cfb:
677             *cipher = &padlock_aes_128_cfb;
678             break;
679           case NID_aes_128_ofb:
680             *cipher = &padlock_aes_128_ofb;
681             break;
682
683           case NID_aes_192_ecb:
684             *cipher = &padlock_aes_192_ecb;
685             break;
686           case NID_aes_192_cbc:
687             *cipher = &padlock_aes_192_cbc;
688             break;
689           case NID_aes_192_cfb:
690             *cipher = &padlock_aes_192_cfb;
691             break;
692           case NID_aes_192_ofb:
693             *cipher = &padlock_aes_192_ofb;
694             break;
695
696           case NID_aes_256_ecb:
697             *cipher = &padlock_aes_256_ecb;
698             break;
699           case NID_aes_256_cbc:
700             *cipher = &padlock_aes_256_cbc;
701             break;
702           case NID_aes_256_cfb:
703             *cipher = &padlock_aes_256_cfb;
704             break;
705           case NID_aes_256_ofb:
706             *cipher = &padlock_aes_256_ofb;
707             break;
708
709           default:
710             /* Sorry, we don't support this NID */
711             *cipher = NULL;
712             return 0;
713         }
714
715         return 1;
716 }
717
718 /* Prepare the encryption key for PadLock usage */
719 static int
720 padlock_aes_init_key (EVP_CIPHER_CTX *ctx, const unsigned char *key,
721                       const unsigned char *iv, int enc)
722 {
723         struct padlock_cipher_data *cdata;
724         int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
725
726         if (key==NULL) return 0;        /* ERROR */
727
728         cdata = ALIGNED_CIPHER_DATA(ctx);
729         memset(cdata, 0, sizeof(struct padlock_cipher_data));
730
731         /* Prepare Control word. */
732         cdata->cword.b.encdec = (ctx->encrypt == 0);
733         cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
734         cdata->cword.b.ksize = (key_len - 128) / 64;
735
736         switch(key_len) {
737                 case 128:
738                         /* PadLock can generate an extended key for
739                            AES128 in hardware */
740                         memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
741                         cdata->cword.b.keygen = 0;
742                         break;
743
744                 case 192:
745                 case 256:
746                         /* Generate an extended AES key in software.
747                            Needed for AES192/AES256 */
748                         /* Well, the above applies to Stepping 8 CPUs
749                            and is listed as hardware errata. They most
750                            likely will fix it at some point and then
751                            a check for stepping would be due here. */
752                         if (enc)
753                                 AES_set_encrypt_key(key, key_len, &cdata->ks);
754                         else
755                                 AES_set_decrypt_key(key, key_len, &cdata->ks);
756
757                         /* OpenSSL internal functions use byte-swapped extended key. */
758                         padlock_bswapl(&cdata->ks);
759
760                         cdata->cword.b.keygen = 1;
761                         break;
762
763                 default:
764                         /* ERROR */
765                         return 0;
766         }
767
768         /*
769          * This is done to cover for cases when user reuses the
770          * context for new key. The catch is that if we don't do
771          * this, padlock_eas_cipher might proceed with old key...
772          */
773         padlock_reload_key ();
774
775         return 1;
776 }
777
778 /* 
779  * Simplified version of padlock_aes_cipher() used when
780  * 1) both input and output buffers are at aligned addresses.
781  * or when
782  * 2) running on a newer CPU that doesn't require aligned buffers.
783  */
784 static int
785 padlock_aes_cipher_omnivorous(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
786                 const unsigned char *in_arg, size_t nbytes)
787 {
788         struct padlock_cipher_data *cdata;
789         void  *iv;
790
791         cdata = ALIGNED_CIPHER_DATA(ctx);
792         padlock_verify_context(cdata);
793
794         switch (EVP_CIPHER_CTX_mode(ctx)) {
795         case EVP_CIPH_ECB_MODE:
796                 padlock_xcrypt_ecb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
797                 break;
798
799         case EVP_CIPH_CBC_MODE:
800                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
801                 iv = padlock_xcrypt_cbc(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
802                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
803                 break;
804
805         case EVP_CIPH_CFB_MODE:
806                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
807                 iv = padlock_xcrypt_cfb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
808                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
809                 break;
810
811         case EVP_CIPH_OFB_MODE:
812                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
813                 padlock_xcrypt_ofb(nbytes/AES_BLOCK_SIZE, cdata, out_arg, in_arg);
814                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
815                 break;
816
817         default:
818                 return 0;
819         }
820
821         memset(cdata->iv, 0, AES_BLOCK_SIZE);
822
823         return 1;
824 }
825
826 #ifndef  PADLOCK_CHUNK
827 # define PADLOCK_CHUNK  4096    /* Must be a power of 2 larger than 16 */
828 #endif
829 #if PADLOCK_CHUNK<16 || PADLOCK_CHUNK&(PADLOCK_CHUNK-1)
830 # error "insane PADLOCK_CHUNK..."
831 #endif
832
833 /* Re-align the arguments to 16-Bytes boundaries and run the 
834    encryption function itself. This function is not AES-specific. */
835 static int
836 padlock_aes_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
837                    const unsigned char *in_arg, size_t nbytes)
838 {
839         struct padlock_cipher_data *cdata;
840         const  void *inp;
841         char  *out;
842         void  *iv;
843         int    inp_misaligned, out_misaligned, realign_in_loop;
844         size_t chunk, allocated=0;
845
846         if (nbytes == 0)
847                 return 1;
848         if (nbytes % AES_BLOCK_SIZE)
849                 return 0; /* are we expected to do tail processing? */
850
851         /* VIA promises CPUs that won't require alignment in the future.
852            For now padlock_aes_align_required is initialized to 1 and
853            the condition is never met... */
854         if (!padlock_aes_align_required)
855                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
856
857         inp_misaligned = (((size_t)in_arg) & 0x0F);
858         out_misaligned = (((size_t)out_arg) & 0x0F);
859
860         /* Note that even if output is aligned and input not,
861          * I still prefer to loop instead of copy the whole
862          * input and then encrypt in one stroke. This is done
863          * in order to improve L1 cache utilization... */
864         realign_in_loop = out_misaligned|inp_misaligned;
865
866         if (!realign_in_loop)
867                 return padlock_aes_cipher_omnivorous(ctx, out_arg, in_arg, nbytes);
868
869         /* this takes one "if" out of the loops */
870         chunk  = nbytes;
871         chunk %= PADLOCK_CHUNK;
872         if (chunk==0) chunk = PADLOCK_CHUNK;
873
874         if (out_misaligned) {
875                 /* optmize for small input */
876                 allocated = (chunk<nbytes?PADLOCK_CHUNK:nbytes);
877                 out = alloca(0x10 + allocated);
878                 out = NEAREST_ALIGNED(out);
879         }
880         else
881                 out = out_arg;
882
883         cdata = ALIGNED_CIPHER_DATA(ctx);
884         padlock_verify_context(cdata);
885
886         switch (EVP_CIPHER_CTX_mode(ctx)) {
887         case EVP_CIPH_ECB_MODE:
888                 do      {
889                         if (inp_misaligned)
890                                 inp = memcpy(out, in_arg, chunk&~3);
891                         else
892                                 inp = in_arg;
893                         in_arg += chunk;
894
895                         padlock_xcrypt_ecb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
896
897                         if (out_misaligned)
898                                 out_arg = (char *)memcpy(out_arg, out, chunk&~3) + chunk;
899                         else
900                                 out     = out_arg+=chunk;
901
902                         nbytes -= chunk;
903                         chunk   = PADLOCK_CHUNK;
904                 } while (nbytes);
905                 break;
906
907         case EVP_CIPH_CBC_MODE:
908                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
909                 goto cbc_shortcut;
910                 do      {
911                         if (iv != cdata->iv)
912                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
913                         chunk = PADLOCK_CHUNK;
914                 cbc_shortcut: /* optimize for small input */
915                         if (inp_misaligned)
916                                 inp = memcpy(out, in_arg, chunk&~3);
917                         else
918                                 inp = in_arg;
919                         in_arg += chunk;
920
921                         iv = padlock_xcrypt_cbc(chunk/AES_BLOCK_SIZE, cdata, out, inp);
922
923                         if (out_misaligned)
924                                 out_arg = (char *)memcpy(out_arg, out, chunk&~3) + chunk;
925                         else
926                                 out     = out_arg+=chunk;
927
928                 } while (nbytes -= chunk);
929                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
930                 break;
931
932         case EVP_CIPH_CFB_MODE:
933                 memcpy (cdata->iv, ctx->iv, AES_BLOCK_SIZE);
934                 goto cfb_shortcut;
935                 do      {
936                         if (iv != cdata->iv)
937                                 memcpy(cdata->iv, iv, AES_BLOCK_SIZE);
938                         chunk = PADLOCK_CHUNK;
939                 cfb_shortcut: /* optimize for small input */
940                         if (inp_misaligned)
941                                 inp = memcpy(out, in_arg, chunk&~3);
942                         else
943                                 inp = in_arg;
944                         in_arg += chunk;
945
946                         iv = padlock_xcrypt_cfb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
947
948                         if (out_misaligned)
949                                 out_arg = (char *)memcpy(out_arg, out, chunk&~3) + chunk;
950                         else
951                                 out     = out_arg+=chunk;
952
953                 } while (nbytes -= chunk);
954                 memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
955                 break;
956
957         case EVP_CIPH_OFB_MODE:
958                 memcpy(cdata->iv, ctx->iv, AES_BLOCK_SIZE);
959                 do      {
960                         if (inp_misaligned)
961                                 inp = memcpy(out, in_arg, chunk&~3);
962                         else
963                                 inp = in_arg;
964                         in_arg += chunk;
965
966                         padlock_xcrypt_ofb(chunk/AES_BLOCK_SIZE, cdata, out, inp);
967
968                         if (out_misaligned)
969                                 out_arg = (char *)memcpy(out_arg, out, chunk&~3) + chunk;
970                         else
971                                 out     = out_arg+=chunk;
972
973                         nbytes -= chunk;
974                         chunk   = PADLOCK_CHUNK;
975                 } while (nbytes);
976                 memcpy(ctx->iv, cdata->iv, AES_BLOCK_SIZE);
977                 break;
978
979         default:
980                 return 0;
981         }
982
983         /* Clean the realign buffer if it was used */
984         if (out_misaligned) {
985                 volatile unsigned long *p=(void *)out;
986                 size_t   n = allocated/sizeof(*p);
987                 while (n--) *p++=0;
988         }
989
990         memset(cdata->iv, 0, AES_BLOCK_SIZE);
991
992         return 1;
993 }
994
995 /* ===== Random Number Generator ===== */
996 /*
997  * This code is not engaged. The reason is that it does not comply
998  * with recommendations for VIA RNG usage for secure applications
999  * (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
1000  * provide meaningful error control...
1001  */
1002 /* Wrapper that provides an interface between the API and 
1003    the raw PadLock RNG */
1004 static int
1005 padlock_rand_bytes(unsigned char *output, int count)
1006 {
1007         unsigned int eax, buf;
1008
1009         while (count >= 8) {
1010                 eax = padlock_xstore(output, 0);
1011                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1012                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1013                 if (eax&(0x1F<<10))     return 0;
1014                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1015                 if ((eax&0x1F)!=8)      return 0; /* fatal failure...  */
1016                 output += 8;
1017                 count  -= 8;
1018         }
1019         while (count > 0) {
1020                 eax = padlock_xstore(&buf, 3);
1021                 if (!(eax&(1<<6)))      return 0; /* RNG disabled */
1022                 /* this ---vv--- covers DC bias, Raw Bits and String Filter */
1023                 if (eax&(0x1F<<10))     return 0;
1024                 if ((eax&0x1F)==0)      continue; /* no data, retry... */
1025                 if ((eax&0x1F)!=1)      return 0; /* fatal failure...  */
1026                 *output++ = (unsigned char)buf;
1027                 count--;
1028         }
1029         *(volatile unsigned int *)&buf=0;
1030
1031         return 1;
1032 }
1033
1034 /* Dummy but necessary function */
1035 static int
1036 padlock_rand_status(void)
1037 {
1038         return 1;
1039 }
1040
1041 /* Prepare structure for registration */
1042 static RAND_METHOD padlock_rand = {
1043         NULL,                   /* seed */
1044         padlock_rand_bytes,     /* bytes */
1045         NULL,                   /* cleanup */
1046         NULL,                   /* add */
1047         padlock_rand_bytes,     /* pseudorand */
1048         padlock_rand_status,    /* rand status */
1049 };
1050
1051 #endif /* COMPILE_HW_PADLOCK */
1052
1053 #endif /* !OPENSSL_NO_HW_PADLOCK */
1054 #endif /* !OPENSSL_NO_HW */