cryptlib.c revision 296465
1/* crypto/cryptlib.c */ 2/* ==================================================================== 3 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * openssl-core@openssl.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 56 * All rights reserved. 57 * 58 * This package is an SSL implementation written 59 * by Eric Young (eay@cryptsoft.com). 60 * The implementation was written so as to conform with Netscapes SSL. 61 * 62 * This library is free for commercial and non-commercial use as long as 63 * the following conditions are aheared to. The following conditions 64 * apply to all code found in this distribution, be it the RC4, RSA, 65 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 66 * included with this distribution is covered by the same copyright terms 67 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 68 * 69 * Copyright remains Eric Young's, and as such any Copyright notices in 70 * the code are not to be removed. 71 * If this package is used in a product, Eric Young should be given attribution 72 * as the author of the parts of the library used. 73 * This can be in the form of a textual message at program startup or 74 * in documentation (online or textual) provided with the package. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. All advertising materials mentioning features or use of this software 85 * must display the following acknowledgement: 86 * "This product includes cryptographic software written by 87 * Eric Young (eay@cryptsoft.com)" 88 * The word 'cryptographic' can be left out if the rouines from the library 89 * being used are not cryptographic related :-). 90 * 4. If you include any Windows specific code (or a derivative thereof) from 91 * the apps directory (application code) you must include an acknowledgement: 92 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 93 * 94 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 95 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 96 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 97 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 98 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 99 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 100 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 101 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 102 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 103 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 104 * SUCH DAMAGE. 105 * 106 * The licence and distribution terms for any publically available version or 107 * derivative of this code cannot be changed. i.e. this code cannot simply be 108 * copied and put under another distribution licence 109 * [including the GNU Public Licence.] 110 */ 111/* ==================================================================== 112 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 113 * ECDH support in OpenSSL originally developed by 114 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 115 */ 116 117#include "cryptlib.h" 118#include <openssl/safestack.h> 119 120#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 121static double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */ 122#endif 123 124static void (MS_FAR *locking_callback) (int mode, int type, 125 const char *file, int line) = NULL; 126static int (MS_FAR *add_lock_callback) (int *pointer, int amount, 127 int type, const char *file, 128 int line) = NULL; 129static unsigned long (MS_FAR *id_callback) (void) = NULL; 130 131int CRYPTO_num_locks(void) 132{ 133 return CRYPTO_NUM_LOCKS; 134} 135 136void (*CRYPTO_get_locking_callback(void)) (int mode, int type, 137 const char *file, int line) { 138 return (locking_callback); 139} 140 141int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type, 142 const char *file, int line) { 143 return (add_lock_callback); 144} 145 146void CRYPTO_set_locking_callback(void (*func) (int mode, int type, 147 const char *file, int line)) 148{ 149 locking_callback = func; 150} 151 152void CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type, 153 const char *file, int line)) 154{ 155 add_lock_callback = func; 156} 157 158unsigned long (*CRYPTO_get_id_callback(void)) (void) { 159 return (id_callback); 160} 161 162void CRYPTO_set_id_callback(unsigned long (*func) (void)) 163{ 164 id_callback = func; 165} 166 167unsigned long CRYPTO_thread_id(void) 168{ 169 unsigned long ret = 0; 170 171 if (id_callback == NULL) { 172#ifdef OPENSSL_SYS_WIN16 173 ret = (unsigned long)GetCurrentTask(); 174#elif defined(OPENSSL_SYS_WIN32) 175 ret = (unsigned long)GetCurrentThreadId(); 176#elif defined(GETPID_IS_MEANINGLESS) 177 ret = 1L; 178#else 179 ret = (unsigned long)getpid(); 180#endif 181 } else 182 ret = id_callback(); 183 return (ret); 184} 185 186static void (*do_dynlock_cb) (int mode, int type, const char *file, int line); 187 188void int_CRYPTO_set_do_dynlock_callback(void (*dyn_cb) 189 (int mode, int type, 190 const char *file, int line)) 191{ 192 do_dynlock_cb = dyn_cb; 193} 194 195void CRYPTO_lock(int mode, int type, const char *file, int line) 196{ 197#ifdef LOCK_DEBUG 198 { 199 char *rw_text, *operation_text; 200 201 if (mode & CRYPTO_LOCK) 202 operation_text = "lock "; 203 else if (mode & CRYPTO_UNLOCK) 204 operation_text = "unlock"; 205 else 206 operation_text = "ERROR "; 207 208 if (mode & CRYPTO_READ) 209 rw_text = "r"; 210 else if (mode & CRYPTO_WRITE) 211 rw_text = "w"; 212 else 213 rw_text = "ERROR"; 214 215 fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n", 216 CRYPTO_thread_id(), rw_text, operation_text, 217 CRYPTO_get_lock_name(type), file, line); 218 } 219#endif 220 if (type < 0) { 221 if (do_dynlock_cb) 222 do_dynlock_cb(mode, type, file, line); 223 } else if (locking_callback != NULL) 224 locking_callback(mode, type, file, line); 225} 226 227int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 228 int line) 229{ 230 int ret = 0; 231 232 if (add_lock_callback != NULL) { 233#ifdef LOCK_DEBUG 234 int before = *pointer; 235#endif 236 237 ret = add_lock_callback(pointer, amount, type, file, line); 238#ifdef LOCK_DEBUG 239 fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 240 CRYPTO_thread_id(), 241 before, amount, ret, CRYPTO_get_lock_name(type), file, line); 242#endif 243 } else { 244 CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line); 245 246 ret = *pointer + amount; 247#ifdef LOCK_DEBUG 248 fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 249 CRYPTO_thread_id(), 250 *pointer, amount, ret, 251 CRYPTO_get_lock_name(type), file, line); 252#endif 253 *pointer = ret; 254 CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line); 255 } 256 return (ret); 257} 258 259#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 260 defined(__INTEL__) || \ 261 defined(__x86_64) || defined(__x86_64__) || \ 262 defined(_M_AMD64) || defined(_M_X64) 263 264unsigned long OPENSSL_ia32cap_P = 0; 265unsigned long *OPENSSL_ia32cap_loc(void) 266{ 267 return &OPENSSL_ia32cap_P; 268} 269 270# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) 271# define OPENSSL_CPUID_SETUP 272void OPENSSL_cpuid_setup(void) 273{ 274 static int trigger = 0; 275 unsigned long OPENSSL_ia32_cpuid(void); 276 char *env; 277 278 if (trigger) 279 return; 280 281 trigger = 1; 282 if ((env = getenv("OPENSSL_ia32cap"))) 283 OPENSSL_ia32cap_P = strtoul(env, NULL, 0) | (1 << 10); 284 else 285 OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid() | (1 << 10); 286 /* 287 * |(1<<10) sets a reserved bit to signal that variable 288 * was initialized already... This is to avoid interference 289 * with cpuid snippets in ELF .init segment. 290 */ 291} 292# endif 293 294#else 295unsigned long *OPENSSL_ia32cap_loc(void) 296{ 297 return NULL; 298} 299#endif 300int OPENSSL_NONPIC_relocated = 0; 301#if !defined(OPENSSL_CPUID_SETUP) 302void OPENSSL_cpuid_setup(void) 303{ 304} 305#endif 306 307#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL) 308 309# ifdef OPENSSL_FIPS 310 311# include <tlhelp32.h> 312# if defined(__GNUC__) && __GNUC__>=2 313static int DllInit(void) __attribute__ ((constructor)); 314# elif defined(_MSC_VER) 315static int DllInit(void); 316# ifdef _WIN64 317# pragma section(".CRT$XCU",read) 318__declspec(allocate(".CRT$XCU")) 319# else 320# pragma data_seg(".CRT$XCU") 321# endif 322static int (*p) (void) = DllInit; 323# pragma data_seg() 324# endif 325 326static int DllInit(void) 327{ 328# if defined(_WIN32_WINNT) 329 union { 330 int (*f) (void); 331 BYTE *p; 332 } t = { 333 DllInit 334 }; 335 HANDLE hModuleSnap = INVALID_HANDLE_VALUE; 336 IMAGE_DOS_HEADER *dos_header; 337 IMAGE_NT_HEADERS *nt_headers; 338 MODULEENTRY32 me32 = { sizeof(me32) }; 339 340 hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); 341 if (hModuleSnap != INVALID_HANDLE_VALUE && 342 Module32First(hModuleSnap, &me32)) 343 do { 344 if (t.p >= me32.modBaseAddr && 345 t.p < me32.modBaseAddr + me32.modBaseSize) { 346 dos_header = (IMAGE_DOS_HEADER *) me32.modBaseAddr; 347 if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { 348 nt_headers = (IMAGE_NT_HEADERS *) 349 ((BYTE *) dos_header + dos_header->e_lfanew); 350 if (nt_headers->Signature == IMAGE_NT_SIGNATURE && 351 me32.modBaseAddr != 352 (BYTE *) nt_headers->OptionalHeader.ImageBase) 353 OPENSSL_NONPIC_relocated = 1; 354 } 355 break; 356 } 357 } while (Module32Next(hModuleSnap, &me32)); 358 359 if (hModuleSnap != INVALID_HANDLE_VALUE) 360 CloseHandle(hModuleSnap); 361# endif 362 OPENSSL_cpuid_setup(); 363 return 0; 364} 365 366# else 367 368# ifdef __CYGWIN__ 369/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ 370# include <windows.h> 371# endif 372 373/* 374 * All we really need to do is remove the 'error' state when a thread 375 * detaches 376 */ 377 378BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 379{ 380 switch (fdwReason) { 381 case DLL_PROCESS_ATTACH: 382 OPENSSL_cpuid_setup(); 383# if defined(_WIN32_WINNT) 384 { 385 IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL; 386 IMAGE_NT_HEADERS *nt_headers; 387 388 if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { 389 nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header 390 + dos_header->e_lfanew); 391 if (nt_headers->Signature == IMAGE_NT_SIGNATURE && 392 hinstDLL != 393 (HINSTANCE) (nt_headers->OptionalHeader.ImageBase)) 394 OPENSSL_NONPIC_relocated = 1; 395 } 396 } 397# endif 398 break; 399 case DLL_THREAD_ATTACH: 400 break; 401 case DLL_THREAD_DETACH: 402 break; 403 case DLL_PROCESS_DETACH: 404 break; 405 } 406 return (TRUE); 407} 408# endif 409 410#endif 411 412#if defined(_WIN32) && !defined(__CYGWIN__) 413# include <tchar.h> 414 415# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 416int OPENSSL_isservice(void) 417{ 418 HWINSTA h; 419 DWORD len; 420 WCHAR *name; 421 422 (void)GetDesktopWindow(); /* return value is ignored */ 423 424 h = GetProcessWindowStation(); 425 if (h == NULL) 426 return -1; 427 428 if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || 429 GetLastError() != ERROR_INSUFFICIENT_BUFFER) 430 return -1; 431 432 if (len > 512) 433 return -1; /* paranoia */ 434 len++, len &= ~1; /* paranoia */ 435# ifdef _MSC_VER 436 name = (WCHAR *)_alloca(len + sizeof(WCHAR)); 437# else 438 name = (WCHAR *)alloca(len + sizeof(WCHAR)); 439# endif 440 if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) 441 return -1; 442 443 len++, len &= ~1; /* paranoia */ 444 name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ 445# if 1 446 /* 447 * This doesn't cover "interactive" services [working with real 448 * WinSta0's] nor programs started non-interactively by Task Scheduler 449 * [those are working with SAWinSta]. 450 */ 451 if (wcsstr(name, L"Service-0x")) 452 return 1; 453# else 454 /* This covers all non-interactive programs such as services. */ 455 if (!wcsstr(name, L"WinSta0")) 456 return 1; 457# endif 458 else 459 return 0; 460} 461# else 462int OPENSSL_isservice(void) 463{ 464 return 0; 465} 466# endif 467 468void OPENSSL_showfatal(const char *fmta, ...) 469{ 470 va_list ap; 471 TCHAR buf[256]; 472 const TCHAR *fmt; 473# ifdef STD_ERROR_HANDLE /* what a dirty trick! */ 474 HANDLE h; 475 476 if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && 477 GetFileType(h) != FILE_TYPE_UNKNOWN) { 478 /* must be console application */ 479 va_start(ap, fmta); 480 vfprintf(stderr, fmta, ap); 481 va_end(ap); 482 return; 483 } 484# endif 485 486 if (sizeof(TCHAR) == sizeof(char)) 487 fmt = (const TCHAR *)fmta; 488 else 489 do { 490 int keepgoing; 491 size_t len_0 = strlen(fmta) + 1, i; 492 WCHAR *fmtw; 493 494# ifdef _MSC_VER 495 fmtw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR)); 496# else 497 fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); 498# endif 499 if (fmtw == NULL) { 500 fmt = (const TCHAR *)L"no stack?"; 501 break; 502 } 503# ifndef OPENSSL_NO_MULTIBYTE 504 if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) 505# endif 506 for (i = 0; i < len_0; i++) 507 fmtw[i] = (WCHAR)fmta[i]; 508 509 for (i = 0; i < len_0; i++) { 510 if (fmtw[i] == L'%') 511 do { 512 keepgoing = 0; 513 switch (fmtw[i + 1]) { 514 case L'0': 515 case L'1': 516 case L'2': 517 case L'3': 518 case L'4': 519 case L'5': 520 case L'6': 521 case L'7': 522 case L'8': 523 case L'9': 524 case L'.': 525 case L'*': 526 case L'-': 527 i++; 528 keepgoing = 1; 529 break; 530 case L's': 531 fmtw[i + 1] = L'S'; 532 break; 533 case L'S': 534 fmtw[i + 1] = L's'; 535 break; 536 case L'c': 537 fmtw[i + 1] = L'C'; 538 break; 539 case L'C': 540 fmtw[i + 1] = L'c'; 541 break; 542 } 543 } while (keepgoing); 544 } 545 fmt = (const TCHAR *)fmtw; 546 } while (0); 547 548 va_start(ap, fmta); 549 _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap); 550 buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0'); 551 va_end(ap); 552 553# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 554 /* this -------------v--- guards NT-specific calls */ 555 if (check_winnt() && OPENSSL_isservice() > 0) { 556 HANDLE h = RegisterEventSource(0, _T("OPENSSL")); 557 const TCHAR *pmsg = buf; 558 ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0); 559 DeregisterEventSource(h); 560 } else 561# endif 562 MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP); 563} 564#else 565void OPENSSL_showfatal(const char *fmta, ...) 566{ 567 va_list ap; 568 569 va_start(ap, fmta); 570 vfprintf(stderr, fmta, ap); 571 va_end(ap); 572} 573 574int OPENSSL_isservice(void) 575{ 576 return 0; 577} 578#endif 579 580void OpenSSLDie(const char *file, int line, const char *assertion) 581{ 582 OPENSSL_showfatal 583 ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line, 584 assertion); 585 abort(); 586} 587 588void *OPENSSL_stderr(void) 589{ 590 return stderr; 591} 592 593#ifndef OPENSSL_FIPS 594 595int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) 596{ 597 size_t i; 598 const unsigned char *a = in_a; 599 const unsigned char *b = in_b; 600 unsigned char x = 0; 601 602 for (i = 0; i < len; i++) 603 x |= a[i] ^ b[i]; 604 605 return x; 606} 607#endif 608