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