~sbeattie/ubuntu/oneiric/openssl/lp850608

« back to all changes in this revision

Viewing changes to crypto/engine/eng_padlock.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2011-05-01 23:51:53 UTC
  • mfrom: (11.1.20 sid)
  • Revision ID: james.westby@ubuntu.com-20110501235153-bjcxitndquaezb68
Tags: 1.0.0d-2ubuntu1
* Resynchronise with Debian (LP: #675566).  Remaining changes:
  - debian/libssl1.0.0.postinst:
    + Display a system restart required notification bubble on libssl1.0.0
      upgrade.
    + Use a different priority for libssl1.0.0/restart-services depending
      on whether a desktop, or server dist-upgrade is being performed.
  - debian/{libssl1.0.0-udeb.dirs, control, rules}: Create
    libssl1.0.0-udeb, for the benefit of wget-udeb (no wget-udeb package
    in Debian).
  - debian/{libcrypto1.0.0-udeb.dirs, libssl1.0.0.dirs, libssl1.0.0.files,
    rules}: Move runtime libraries to /lib, for the benefit of
    wpasupplicant.
  - debian/patches/aesni.patch: Backport Intel AES-NI support, now from
    http://rt.openssl.org/Ticket/Display.html?id=2065 rather than the
    0.9.8 variant.
  - debian/patches/Bsymbolic-functions.patch: Link using
    -Bsymbolic-functions.
  - debian/patches/perlpath-quilt.patch: Don't change perl #! paths under
    .pc.
  - debian/rules:
    + Don't run 'make test' when cross-building.
    + Use host compiler when cross-building.  Patch from Neil Williams.
    + Don't build for processors no longer supported: i486, i586 (on
      i386), v8 (on sparc).
    + Fix Makefile to properly clean up libs/ dirs in clean target.
    + Replace duplicate files in the doc directory with symlinks.
* Update architectures affected by Bsymbolic-functions.patch.
* Drop debian/patches/no-sslv2.patch; Debian now adds the 'no-ssl2'
  configure option, which compiles out SSLv2 support entirely, so this is
  no longer needed.
* Drop openssl-doc in favour of the libssl-doc package introduced by
  Debian.  Add Conflicts/Replaces until the next LTS release.

Show diffs side-by-side

added added

removed removed

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