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