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