155714Skris/* crypto/cryptlib.c */ 2160814Ssimon/* ==================================================================== 3238405Sjkim * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 4160814Ssimon * 5160814Ssimon * Redistribution and use in source and binary forms, with or without 6160814Ssimon * modification, are permitted provided that the following conditions 7160814Ssimon * are met: 8160814Ssimon * 9160814Ssimon * 1. Redistributions of source code must retain the above copyright 10280304Sjkim * notice, this list of conditions and the following disclaimer. 11160814Ssimon * 12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer in 14160814Ssimon * the documentation and/or other materials provided with the 15160814Ssimon * distribution. 16160814Ssimon * 17160814Ssimon * 3. All advertising materials mentioning features or use of this 18160814Ssimon * software must display the following acknowledgment: 19160814Ssimon * "This product includes software developed by the OpenSSL Project 20160814Ssimon * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21160814Ssimon * 22160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23160814Ssimon * endorse or promote products derived from this software without 24160814Ssimon * prior written permission. For written permission, please contact 25160814Ssimon * openssl-core@openssl.org. 26160814Ssimon * 27160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 28160814Ssimon * nor may "OpenSSL" appear in their names without prior written 29160814Ssimon * permission of the OpenSSL Project. 30160814Ssimon * 31160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 32160814Ssimon * acknowledgment: 33160814Ssimon * "This product includes software developed by the OpenSSL Project 34160814Ssimon * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35160814Ssimon * 36160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 48160814Ssimon * ==================================================================== 49160814Ssimon * 50160814Ssimon * This product includes cryptographic software written by Eric Young 51160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 52160814Ssimon * Hudson (tjh@cryptsoft.com). 53160814Ssimon * 54160814Ssimon */ 5555714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 5655714Skris * All rights reserved. 5755714Skris * 5855714Skris * This package is an SSL implementation written 5955714Skris * by Eric Young (eay@cryptsoft.com). 6055714Skris * The implementation was written so as to conform with Netscapes SSL. 61280304Sjkim * 6255714Skris * This library is free for commercial and non-commercial use as long as 6355714Skris * the following conditions are aheared to. The following conditions 6455714Skris * apply to all code found in this distribution, be it the RC4, RSA, 6555714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 6655714Skris * included with this distribution is covered by the same copyright terms 6755714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 68280304Sjkim * 6955714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 7055714Skris * the code are not to be removed. 7155714Skris * If this package is used in a product, Eric Young should be given attribution 7255714Skris * as the author of the parts of the library used. 7355714Skris * This can be in the form of a textual message at program startup or 7455714Skris * in documentation (online or textual) provided with the package. 75280304Sjkim * 7655714Skris * Redistribution and use in source and binary forms, with or without 7755714Skris * modification, are permitted provided that the following conditions 7855714Skris * are met: 7955714Skris * 1. Redistributions of source code must retain the copyright 8055714Skris * notice, this list of conditions and the following disclaimer. 8155714Skris * 2. Redistributions in binary form must reproduce the above copyright 8255714Skris * notice, this list of conditions and the following disclaimer in the 8355714Skris * documentation and/or other materials provided with the distribution. 8455714Skris * 3. All advertising materials mentioning features or use of this software 8555714Skris * must display the following acknowledgement: 8655714Skris * "This product includes cryptographic software written by 8755714Skris * Eric Young (eay@cryptsoft.com)" 8855714Skris * The word 'cryptographic' can be left out if the rouines from the library 8955714Skris * being used are not cryptographic related :-). 90280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 9155714Skris * the apps directory (application code) you must include an acknowledgement: 9255714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 93280304Sjkim * 9455714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 9555714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9655714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9755714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 9855714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 9955714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10055714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 10155714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 10255714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 10355714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 10455714Skris * SUCH DAMAGE. 105280304Sjkim * 10655714Skris * The licence and distribution terms for any publically available version or 10755714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 10855714Skris * copied and put under another distribution licence 10955714Skris * [including the GNU Public Licence.] 11055714Skris */ 111160814Ssimon/* ==================================================================== 112160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 113280304Sjkim * ECDH support in OpenSSL originally developed by 114160814Ssimon * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. 115160814Ssimon */ 11655714Skris 11755714Skris#include "cryptlib.h" 11868651Skris#include <openssl/safestack.h> 11955714Skris 120109998Smarkm#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 121280304Sjkimstatic double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */ 12255714Skris#endif 12355714Skris 124238405SjkimDECLARE_STACK_OF(CRYPTO_dynlock) 125238405Sjkim 126238405Sjkim/* real #defines in crypto.h, keep these upto date */ 127280304Sjkimstatic const char *const lock_names[CRYPTO_NUM_LOCKS] = { 128280304Sjkim "<<ERROR>>", 129280304Sjkim "err", 130280304Sjkim "ex_data", 131280304Sjkim "x509", 132280304Sjkim "x509_info", 133280304Sjkim "x509_pkey", 134280304Sjkim "x509_crl", 135280304Sjkim "x509_req", 136280304Sjkim "dsa", 137280304Sjkim "rsa", 138280304Sjkim "evp_pkey", 139280304Sjkim "x509_store", 140280304Sjkim "ssl_ctx", 141280304Sjkim "ssl_cert", 142280304Sjkim "ssl_session", 143280304Sjkim "ssl_sess_cert", 144280304Sjkim "ssl", 145280304Sjkim "ssl_method", 146280304Sjkim "rand", 147280304Sjkim "rand2", 148280304Sjkim "debug_malloc", 149280304Sjkim "BIO", 150280304Sjkim "gethostbyname", 151280304Sjkim "getservbyname", 152280304Sjkim "readdir", 153280304Sjkim "RSA_blinding", 154280304Sjkim "dh", 155280304Sjkim "debug_malloc2", 156280304Sjkim "dso", 157280304Sjkim "dynlock", 158280304Sjkim "engine", 159280304Sjkim "ui", 160280304Sjkim "ecdsa", 161280304Sjkim "ec", 162280304Sjkim "ecdh", 163280304Sjkim "bn", 164280304Sjkim "ec_pre_comp", 165280304Sjkim "store", 166280304Sjkim "comp", 167280304Sjkim "fips", 168280304Sjkim "fips2", 169238405Sjkim#if CRYPTO_NUM_LOCKS != 41 170238405Sjkim# error "Inconsistency between crypto.h and cryptlib.c" 171238405Sjkim#endif 172280304Sjkim}; 173238405Sjkim 174280304Sjkim/* 175280304Sjkim * This is for applications to allocate new type names in the non-dynamic 176280304Sjkim * array of lock names. These are numbered with positive numbers. 177280304Sjkim */ 178280304Sjkimstatic STACK_OF(OPENSSL_STRING) *app_locks = NULL; 179238405Sjkim 180280304Sjkim/* 181280304Sjkim * For applications that want a more dynamic way of handling threads, the 182280304Sjkim * following stack is used. These are externally numbered with negative 183280304Sjkim * numbers. 184280304Sjkim */ 185280304Sjkimstatic STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL; 186238405Sjkim 187280304Sjkimstatic void (MS_FAR *locking_callback) (int mode, int type, 188280304Sjkim const char *file, int line) = 0; 189280304Sjkimstatic int (MS_FAR *add_lock_callback) (int *pointer, int amount, 190280304Sjkim int type, const char *file, 191280304Sjkim int line) = 0; 192238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 193280304Sjkimstatic unsigned long (MS_FAR *id_callback) (void) = 0; 194238405Sjkim#endif 195280304Sjkimstatic void (MS_FAR *threadid_callback) (CRYPTO_THREADID *) = 0; 196238405Sjkimstatic struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback) 197280304Sjkim (const char *file, int line) = 0; 198280304Sjkimstatic void (MS_FAR *dynlock_lock_callback) (int mode, 199280304Sjkim struct CRYPTO_dynlock_value *l, 200280304Sjkim const char *file, int line) = 0; 201280304Sjkimstatic void (MS_FAR *dynlock_destroy_callback) (struct CRYPTO_dynlock_value 202280304Sjkim *l, const char *file, 203280304Sjkim int line) = 0; 20468651Skris 205238405Sjkimint CRYPTO_get_new_lockid(char *name) 206280304Sjkim{ 207280304Sjkim char *str; 208280304Sjkim int i; 209238405Sjkim 210238405Sjkim#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 211280304Sjkim /* 212280304Sjkim * A hack to make Visual C++ 5.0 work correctly when linking as a DLL 213280304Sjkim * using /MT. Without this, the application cannot use any floating point 214280304Sjkim * printf's. It also seems to be needed for Visual C 1.5 (win16) 215280304Sjkim */ 216280304Sjkim SSLeay_MSVC5_hack = (double)name[0] * (double)name[1]; 217238405Sjkim#endif 218238405Sjkim 219280304Sjkim if ((app_locks == NULL) 220280304Sjkim && ((app_locks = sk_OPENSSL_STRING_new_null()) == NULL)) { 221280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE); 222280304Sjkim return (0); 223280304Sjkim } 224280304Sjkim if ((str = BUF_strdup(name)) == NULL) { 225280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE); 226280304Sjkim return (0); 227280304Sjkim } 228280304Sjkim i = sk_OPENSSL_STRING_push(app_locks, str); 229280304Sjkim if (!i) 230280304Sjkim OPENSSL_free(str); 231280304Sjkim else 232280304Sjkim i += CRYPTO_NUM_LOCKS; /* gap of one :-) */ 233280304Sjkim return (i); 234280304Sjkim} 235238405Sjkim 23655714Skrisint CRYPTO_num_locks(void) 237280304Sjkim{ 238280304Sjkim return CRYPTO_NUM_LOCKS; 239280304Sjkim} 24055714Skris 241238405Sjkimint CRYPTO_get_new_dynlockid(void) 242280304Sjkim{ 243280304Sjkim int i = 0; 244280304Sjkim CRYPTO_dynlock *pointer = NULL; 245238405Sjkim 246280304Sjkim if (dynlock_create_callback == NULL) { 247280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, 248280304Sjkim CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK); 249280304Sjkim return (0); 250280304Sjkim } 251280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 252280304Sjkim if ((dyn_locks == NULL) 253280304Sjkim && ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) { 254280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 255280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE); 256280304Sjkim return (0); 257280304Sjkim } 258280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 259238405Sjkim 260280304Sjkim pointer = (CRYPTO_dynlock *) OPENSSL_malloc(sizeof(CRYPTO_dynlock)); 261280304Sjkim if (pointer == NULL) { 262280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE); 263280304Sjkim return (0); 264280304Sjkim } 265280304Sjkim pointer->references = 1; 266280304Sjkim pointer->data = dynlock_create_callback(__FILE__, __LINE__); 267280304Sjkim if (pointer->data == NULL) { 268280304Sjkim OPENSSL_free(pointer); 269280304Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE); 270280304Sjkim return (0); 271280304Sjkim } 272238405Sjkim 273280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 274280304Sjkim /* First, try to find an existing empty slot */ 275280304Sjkim i = sk_CRYPTO_dynlock_find(dyn_locks, NULL); 276280304Sjkim /* If there was none, push, thereby creating a new one */ 277280304Sjkim if (i == -1) 278280304Sjkim /* 279280304Sjkim * Since sk_push() returns the number of items on the stack, not the 280280304Sjkim * location of the pushed item, we need to transform the returned 281280304Sjkim * number into a position, by decreasing it. 282280304Sjkim */ 283280304Sjkim i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1; 284280304Sjkim else 285280304Sjkim /* 286280304Sjkim * If we found a place with a NULL pointer, put our pointer in it. 287280304Sjkim */ 288280304Sjkim (void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer); 289280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 290238405Sjkim 291280304Sjkim if (i == -1) { 292280304Sjkim dynlock_destroy_callback(pointer->data, __FILE__, __LINE__); 293280304Sjkim OPENSSL_free(pointer); 294280304Sjkim } else 295280304Sjkim i += 1; /* to avoid 0 */ 296280304Sjkim return -i; 297280304Sjkim} 298238405Sjkim 299238405Sjkimvoid CRYPTO_destroy_dynlockid(int i) 300280304Sjkim{ 301280304Sjkim CRYPTO_dynlock *pointer = NULL; 302280304Sjkim if (i) 303280304Sjkim i = -i - 1; 304280304Sjkim if (dynlock_destroy_callback == NULL) 305280304Sjkim return; 306238405Sjkim 307280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 308238405Sjkim 309280304Sjkim if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) { 310280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 311280304Sjkim return; 312280304Sjkim } 313280304Sjkim pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 314280304Sjkim if (pointer != NULL) { 315280304Sjkim --pointer->references; 316238405Sjkim#ifdef REF_CHECK 317280304Sjkim if (pointer->references < 0) { 318280304Sjkim fprintf(stderr, 319280304Sjkim "CRYPTO_destroy_dynlockid, bad reference count\n"); 320280304Sjkim abort(); 321280304Sjkim } else 322238405Sjkim#endif 323280304Sjkim if (pointer->references <= 0) { 324280304Sjkim (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); 325280304Sjkim } else 326280304Sjkim pointer = NULL; 327280304Sjkim } 328280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 329238405Sjkim 330280304Sjkim if (pointer) { 331280304Sjkim dynlock_destroy_callback(pointer->data, __FILE__, __LINE__); 332280304Sjkim OPENSSL_free(pointer); 333280304Sjkim } 334280304Sjkim} 335238405Sjkim 336238405Sjkimstruct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i) 337280304Sjkim{ 338280304Sjkim CRYPTO_dynlock *pointer = NULL; 339280304Sjkim if (i) 340280304Sjkim i = -i - 1; 341238405Sjkim 342280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 343238405Sjkim 344280304Sjkim if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks)) 345280304Sjkim pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 346280304Sjkim if (pointer) 347280304Sjkim pointer->references++; 348238405Sjkim 349280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 350238405Sjkim 351280304Sjkim if (pointer) 352280304Sjkim return pointer->data; 353280304Sjkim return NULL; 354280304Sjkim} 355238405Sjkim 356238405Sjkimstruct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void)) 357280304Sjkim (const char *file, int line) { 358280304Sjkim return (dynlock_create_callback); 359280304Sjkim} 360238405Sjkim 361280304Sjkimvoid (*CRYPTO_get_dynlock_lock_callback(void)) (int mode, 362280304Sjkim struct CRYPTO_dynlock_value 363280304Sjkim *l, const char *file, 364280304Sjkim int line) { 365280304Sjkim return (dynlock_lock_callback); 366280304Sjkim} 367238405Sjkim 368238405Sjkimvoid (*CRYPTO_get_dynlock_destroy_callback(void)) 369280304Sjkim (struct CRYPTO_dynlock_value *l, const char *file, int line) { 370280304Sjkim return (dynlock_destroy_callback); 371280304Sjkim} 372238405Sjkim 373238405Sjkimvoid CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func) 374280304Sjkim (const char *file, int line)) 375280304Sjkim{ 376280304Sjkim dynlock_create_callback = func; 377280304Sjkim} 378238405Sjkim 379280304Sjkimvoid CRYPTO_set_dynlock_lock_callback(void (*func) (int mode, 380280304Sjkim struct 381280304Sjkim CRYPTO_dynlock_value *l, 382280304Sjkim const char *file, 383280304Sjkim int line)) 384280304Sjkim{ 385280304Sjkim dynlock_lock_callback = func; 386280304Sjkim} 387238405Sjkim 388238405Sjkimvoid CRYPTO_set_dynlock_destroy_callback(void (*func) 389280304Sjkim (struct CRYPTO_dynlock_value *l, 390280304Sjkim const char *file, int line)) 391280304Sjkim{ 392280304Sjkim dynlock_destroy_callback = func; 393280304Sjkim} 394238405Sjkim 395280304Sjkimvoid (*CRYPTO_get_locking_callback(void)) (int mode, int type, 396280304Sjkim const char *file, int line) { 397280304Sjkim return (locking_callback); 398280304Sjkim} 399238405Sjkim 400280304Sjkimint (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type, 401280304Sjkim const char *file, int line) { 402280304Sjkim return (add_lock_callback); 403280304Sjkim} 40455714Skris 405280304Sjkimvoid CRYPTO_set_locking_callback(void (*func) (int mode, int type, 406280304Sjkim const char *file, int line)) 407280304Sjkim{ 408280304Sjkim /* 409280304Sjkim * Calling this here ensures initialisation before any threads are 410280304Sjkim * started. 411280304Sjkim */ 412280304Sjkim OPENSSL_init(); 413280304Sjkim locking_callback = func; 414280304Sjkim} 41555714Skris 416280304Sjkimvoid CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type, 417280304Sjkim const char *file, int line)) 418280304Sjkim{ 419280304Sjkim add_lock_callback = func; 420280304Sjkim} 42155714Skris 422280304Sjkim/* 423280304Sjkim * the memset() here and in set_pointer() seem overkill, but for the sake of 424280304Sjkim * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause 425280304Sjkim * two "equal" THREADID structs to not be memcmp()-identical. 426280304Sjkim */ 427238405Sjkimvoid CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) 428280304Sjkim{ 429280304Sjkim memset(id, 0, sizeof(*id)); 430280304Sjkim id->val = val; 431280304Sjkim} 432238405Sjkim 433238405Sjkimstatic const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 }; 434280304Sjkim 435238405Sjkimvoid CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) 436280304Sjkim{ 437280304Sjkim unsigned char *dest = (void *)&id->val; 438280304Sjkim unsigned int accum = 0; 439280304Sjkim unsigned char dnum = sizeof(id->val); 440238405Sjkim 441280304Sjkim memset(id, 0, sizeof(*id)); 442280304Sjkim id->ptr = ptr; 443280304Sjkim if (sizeof(id->val) >= sizeof(id->ptr)) { 444280304Sjkim /* 445280304Sjkim * 'ptr' can be embedded in 'val' without loss of uniqueness 446280304Sjkim */ 447280304Sjkim id->val = (unsigned long)id->ptr; 448280304Sjkim return; 449280304Sjkim } 450280304Sjkim /* 451280304Sjkim * hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a 452280304Sjkim * linear function over the bytes in 'ptr', the co-efficients of which 453280304Sjkim * are a sequence of low-primes (hash_coeffs is an 8-element cycle) - the 454280304Sjkim * starting prime for the sequence varies for each byte of 'val' (unique 455280304Sjkim * polynomials unless pointers are >64-bit). For added spice, the totals 456280304Sjkim * accumulate rather than restarting from zero, and the index of the 457280304Sjkim * 'val' byte is added each time (position dependence). If I was a 458280304Sjkim * black-belt, I'd scan big-endian pointers in reverse to give low-order 459280304Sjkim * bits more play, but this isn't crypto and I'd prefer nobody mistake it 460280304Sjkim * as such. Plus I'm lazy. 461280304Sjkim */ 462280304Sjkim while (dnum--) { 463280304Sjkim const unsigned char *src = (void *)&id->ptr; 464280304Sjkim unsigned char snum = sizeof(id->ptr); 465280304Sjkim while (snum--) 466280304Sjkim accum += *(src++) * hash_coeffs[(snum + dnum) & 7]; 467280304Sjkim accum += dnum; 468280304Sjkim *(dest++) = accum & 255; 469280304Sjkim } 470280304Sjkim} 471238405Sjkim 472280304Sjkimint CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *)) 473280304Sjkim{ 474280304Sjkim if (threadid_callback) 475280304Sjkim return 0; 476280304Sjkim threadid_callback = func; 477280304Sjkim return 1; 478280304Sjkim} 479238405Sjkim 480280304Sjkimvoid (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *) { 481280304Sjkim return threadid_callback; 482280304Sjkim} 483238405Sjkim 484238405Sjkimvoid CRYPTO_THREADID_current(CRYPTO_THREADID *id) 485280304Sjkim{ 486280304Sjkim if (threadid_callback) { 487280304Sjkim threadid_callback(id); 488280304Sjkim return; 489280304Sjkim } 490238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 491280304Sjkim /* If the deprecated callback was set, fall back to that */ 492280304Sjkim if (id_callback) { 493280304Sjkim CRYPTO_THREADID_set_numeric(id, id_callback()); 494280304Sjkim return; 495280304Sjkim } 496238405Sjkim#endif 497280304Sjkim /* Else pick a backup */ 498238405Sjkim#ifdef OPENSSL_SYS_WIN16 499280304Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask()); 500238405Sjkim#elif defined(OPENSSL_SYS_WIN32) 501280304Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId()); 502238405Sjkim#elif defined(OPENSSL_SYS_BEOS) 503280304Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL)); 504238405Sjkim#else 505280304Sjkim /* For everything else, default to using the address of 'errno' */ 506280304Sjkim CRYPTO_THREADID_set_pointer(id, (void *)&errno); 507238405Sjkim#endif 508280304Sjkim} 509238405Sjkim 510238405Sjkimint CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b) 511280304Sjkim{ 512280304Sjkim return memcmp(a, b, sizeof(*a)); 513280304Sjkim} 514238405Sjkim 515238405Sjkimvoid CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src) 516280304Sjkim{ 517280304Sjkim memcpy(dest, src, sizeof(*src)); 518280304Sjkim} 519238405Sjkim 520238405Sjkimunsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id) 521280304Sjkim{ 522280304Sjkim return id->val; 523280304Sjkim} 524238405Sjkim 525238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 526280304Sjkimunsigned long (*CRYPTO_get_id_callback(void)) (void) { 527280304Sjkim return (id_callback); 528280304Sjkim} 52955714Skris 530280304Sjkimvoid CRYPTO_set_id_callback(unsigned long (*func) (void)) 531280304Sjkim{ 532280304Sjkim id_callback = func; 533280304Sjkim} 53455714Skris 53555714Skrisunsigned long CRYPTO_thread_id(void) 536280304Sjkim{ 537280304Sjkim unsigned long ret = 0; 53855714Skris 539280304Sjkim if (id_callback == NULL) { 540280304Sjkim# ifdef OPENSSL_SYS_WIN16 541280304Sjkim ret = (unsigned long)GetCurrentTask(); 542280304Sjkim# elif defined(OPENSSL_SYS_WIN32) 543280304Sjkim ret = (unsigned long)GetCurrentThreadId(); 544280304Sjkim# elif defined(GETPID_IS_MEANINGLESS) 545280304Sjkim ret = 1L; 546280304Sjkim# elif defined(OPENSSL_SYS_BEOS) 547280304Sjkim ret = (unsigned long)find_thread(NULL); 548280304Sjkim# else 549280304Sjkim ret = (unsigned long)getpid(); 550280304Sjkim# endif 551280304Sjkim } else 552280304Sjkim ret = id_callback(); 553280304Sjkim return (ret); 554280304Sjkim} 55555714Skris#endif 55655714Skris 55755714Skrisvoid CRYPTO_lock(int mode, int type, const char *file, int line) 558280304Sjkim{ 55955714Skris#ifdef LOCK_DEBUG 560280304Sjkim { 561280304Sjkim CRYPTO_THREADID id; 562280304Sjkim char *rw_text, *operation_text; 56355714Skris 564280304Sjkim if (mode & CRYPTO_LOCK) 565280304Sjkim operation_text = "lock "; 566280304Sjkim else if (mode & CRYPTO_UNLOCK) 567280304Sjkim operation_text = "unlock"; 568280304Sjkim else 569280304Sjkim operation_text = "ERROR "; 57055714Skris 571280304Sjkim if (mode & CRYPTO_READ) 572280304Sjkim rw_text = "r"; 573280304Sjkim else if (mode & CRYPTO_WRITE) 574280304Sjkim rw_text = "w"; 575280304Sjkim else 576280304Sjkim rw_text = "ERROR"; 57755714Skris 578280304Sjkim CRYPTO_THREADID_current(&id); 579280304Sjkim fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n", 580280304Sjkim CRYPTO_THREADID_hash(&id), rw_text, operation_text, 581280304Sjkim CRYPTO_get_lock_name(type), file, line); 582280304Sjkim } 58355714Skris#endif 584280304Sjkim if (type < 0) { 585280304Sjkim if (dynlock_lock_callback != NULL) { 586280304Sjkim struct CRYPTO_dynlock_value *pointer 587280304Sjkim = CRYPTO_get_dynlock_value(type); 588238405Sjkim 589280304Sjkim OPENSSL_assert(pointer != NULL); 590238405Sjkim 591280304Sjkim dynlock_lock_callback(mode, pointer, file, line); 592238405Sjkim 593280304Sjkim CRYPTO_destroy_dynlockid(type); 594280304Sjkim } 595280304Sjkim } else if (locking_callback != NULL) 596280304Sjkim locking_callback(mode, type, file, line); 597280304Sjkim} 59855714Skris 59955714Skrisint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 600280304Sjkim int line) 601280304Sjkim{ 602280304Sjkim int ret = 0; 60355714Skris 604280304Sjkim if (add_lock_callback != NULL) { 60555714Skris#ifdef LOCK_DEBUG 606280304Sjkim int before = *pointer; 60755714Skris#endif 60855714Skris 609280304Sjkim ret = add_lock_callback(pointer, amount, type, file, line); 61055714Skris#ifdef LOCK_DEBUG 611280304Sjkim { 612280304Sjkim CRYPTO_THREADID id; 613280304Sjkim CRYPTO_THREADID_current(&id); 614280304Sjkim fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 615280304Sjkim CRYPTO_THREADID_hash(&id), before, amount, ret, 616280304Sjkim CRYPTO_get_lock_name(type), file, line); 617280304Sjkim } 61855714Skris#endif 619280304Sjkim } else { 620280304Sjkim CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line); 62155714Skris 622280304Sjkim ret = *pointer + amount; 62355714Skris#ifdef LOCK_DEBUG 624280304Sjkim { 625280304Sjkim CRYPTO_THREADID id; 626280304Sjkim CRYPTO_THREADID_current(&id); 627280304Sjkim fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 628280304Sjkim CRYPTO_THREADID_hash(&id), 629280304Sjkim *pointer, amount, ret, 630280304Sjkim CRYPTO_get_lock_name(type), file, line); 631280304Sjkim } 63255714Skris#endif 633280304Sjkim *pointer = ret; 634280304Sjkim CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line); 635280304Sjkim } 636280304Sjkim return (ret); 637280304Sjkim} 63855714Skris 639238405Sjkimconst char *CRYPTO_get_lock_name(int type) 640280304Sjkim{ 641280304Sjkim if (type < 0) 642280304Sjkim return ("dynamic"); 643280304Sjkim else if (type < CRYPTO_NUM_LOCKS) 644280304Sjkim return (lock_names[type]); 645280304Sjkim else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks)) 646280304Sjkim return ("ERROR"); 647280304Sjkim else 648280304Sjkim return (sk_OPENSSL_STRING_value(app_locks, type - CRYPTO_NUM_LOCKS)); 649280304Sjkim} 650238405Sjkim 651280304Sjkim#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 652280304Sjkim defined(__INTEL__) || \ 653280304Sjkim defined(__x86_64) || defined(__x86_64__) || \ 654280304Sjkim defined(_M_AMD64) || defined(_M_X64) 65555714Skris 656280304Sjkimunsigned int OPENSSL_ia32cap_P[2]; 657238405Sjkimunsigned long *OPENSSL_ia32cap_loc(void) 658280304Sjkim{ 659280304Sjkim if (sizeof(long) == 4) 660280304Sjkim /* 661280304Sjkim * If 32-bit application pulls address of OPENSSL_ia32cap_P[0] 662280304Sjkim * clear second element to maintain the illusion that vector 663280304Sjkim * is 32-bit. 664280304Sjkim */ 665280304Sjkim OPENSSL_ia32cap_P[1] = 0; 666238405Sjkim return (unsigned long *)OPENSSL_ia32cap_P; 667238405Sjkim} 668160814Ssimon 669280304Sjkim# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) 670280304Sjkim# define OPENSSL_CPUID_SETUP 671280304Sjkim# if defined(_WIN32) 672238405Sjkimtypedef unsigned __int64 IA32CAP; 673280304Sjkim# else 674238405Sjkimtypedef unsigned long long IA32CAP; 675280304Sjkim# endif 676160814Ssimonvoid OPENSSL_cpuid_setup(void) 677280304Sjkim{ 678280304Sjkim static int trigger = 0; 679280304Sjkim IA32CAP OPENSSL_ia32_cpuid(void); 680280304Sjkim IA32CAP vec; 681280304Sjkim char *env; 682160814Ssimon 683280304Sjkim if (trigger) 684280304Sjkim return; 685160814Ssimon 686280304Sjkim trigger = 1; 687280304Sjkim if ((env = getenv("OPENSSL_ia32cap"))) { 688280304Sjkim int off = (env[0] == '~') ? 1 : 0; 689280304Sjkim# if defined(_WIN32) 690280304Sjkim if (!sscanf(env + off, "%I64i", &vec)) 691280304Sjkim vec = strtoul(env + off, NULL, 0); 692280304Sjkim# else 693280304Sjkim if (!sscanf(env + off, "%lli", (long long *)&vec)) 694280304Sjkim vec = strtoul(env + off, NULL, 0); 695280304Sjkim# endif 696280304Sjkim if (off) 697280304Sjkim vec = OPENSSL_ia32_cpuid() & ~vec; 698280304Sjkim } else 699280304Sjkim vec = OPENSSL_ia32_cpuid(); 700246772Sjkim 701160814Ssimon /* 702160814Ssimon * |(1<<10) sets a reserved bit to signal that variable 703160814Ssimon * was initialized already... This is to avoid interference 704160814Ssimon * with cpuid snippets in ELF .init segment. 705160814Ssimon */ 706280304Sjkim OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); 707280304Sjkim OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); 708160814Ssimon} 709280304Sjkim# endif 710160814Ssimon 711160814Ssimon#else 712280304Sjkimunsigned long *OPENSSL_ia32cap_loc(void) 713280304Sjkim{ 714280304Sjkim return NULL; 715280304Sjkim} 716160814Ssimon#endif 717160814Ssimonint OPENSSL_NONPIC_relocated = 0; 718238405Sjkim#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) 719280304Sjkimvoid OPENSSL_cpuid_setup(void) 720280304Sjkim{ 721280304Sjkim} 722160814Ssimon#endif 723160814Ssimon 724160814Ssimon#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL) 725280304Sjkim# ifdef __CYGWIN__ 726160814Ssimon/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ 727280304Sjkim# include <windows.h> 728280304Sjkim/* 729280304Sjkim * this has side-effect of _WIN32 getting defined, which otherwise is 730280304Sjkim * mutually exclusive with __CYGWIN__... 731280304Sjkim */ 732280304Sjkim# endif 733160814Ssimon 734280304Sjkim/* 735280304Sjkim * All we really need to do is remove the 'error' state when a thread 736280304Sjkim * detaches 737280304Sjkim */ 73855714Skris 739280304SjkimBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 740280304Sjkim{ 741280304Sjkim switch (fdwReason) { 742280304Sjkim case DLL_PROCESS_ATTACH: 743280304Sjkim OPENSSL_cpuid_setup(); 744280304Sjkim# if defined(_WIN32_WINNT) 745280304Sjkim { 746280304Sjkim IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL; 747280304Sjkim IMAGE_NT_HEADERS *nt_headers; 748160814Ssimon 749280304Sjkim if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) { 750280304Sjkim nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header 751280304Sjkim + dos_header->e_lfanew); 752280304Sjkim if (nt_headers->Signature == IMAGE_NT_SIGNATURE && 753280304Sjkim hinstDLL != 754280304Sjkim (HINSTANCE) (nt_headers->OptionalHeader.ImageBase)) 755280304Sjkim OPENSSL_NONPIC_relocated = 1; 756280304Sjkim } 757280304Sjkim } 758280304Sjkim# endif 759280304Sjkim break; 760280304Sjkim case DLL_THREAD_ATTACH: 761280304Sjkim break; 762280304Sjkim case DLL_THREAD_DETACH: 763280304Sjkim break; 764280304Sjkim case DLL_PROCESS_DETACH: 765280304Sjkim break; 766280304Sjkim } 767280304Sjkim return (TRUE); 768280304Sjkim} 769160814Ssimon#endif 77055714Skris 771160814Ssimon#if defined(_WIN32) && !defined(__CYGWIN__) 772280304Sjkim# include <tchar.h> 773280304Sjkim# include <signal.h> 774280304Sjkim# ifdef __WATCOMC__ 775280304Sjkim# if defined(_UNICODE) || defined(__UNICODE__) 776280304Sjkim# define _vsntprintf _vsnwprintf 777280304Sjkim# else 778280304Sjkim# define _vsntprintf _vsnprintf 779280304Sjkim# endif 780280304Sjkim# endif 781280304Sjkim# ifdef _MSC_VER 782280304Sjkim# define alloca _alloca 783280304Sjkim# endif 784109998Smarkm 785280304Sjkim# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 786160814Ssimonint OPENSSL_isservice(void) 787280304Sjkim{ 788280304Sjkim HWINSTA h; 789280304Sjkim DWORD len; 790280304Sjkim WCHAR *name; 791280304Sjkim static union { 792280304Sjkim void *p; 793280304Sjkim int (*f) (void); 794280304Sjkim } _OPENSSL_isservice = { 795280304Sjkim NULL 796280304Sjkim }; 797142425Snectar 798238405Sjkim if (_OPENSSL_isservice.p == NULL) { 799280304Sjkim HANDLE h = GetModuleHandle(NULL); 800280304Sjkim if (h != NULL) 801280304Sjkim _OPENSSL_isservice.p = GetProcAddress(h, "_OPENSSL_isservice"); 802280304Sjkim if (_OPENSSL_isservice.p == NULL) 803280304Sjkim _OPENSSL_isservice.p = (void *)-1; 804238405Sjkim } 805238405Sjkim 806238405Sjkim if (_OPENSSL_isservice.p != (void *)-1) 807280304Sjkim return (*_OPENSSL_isservice.f) (); 808238405Sjkim 809160814Ssimon h = GetProcessWindowStation(); 810280304Sjkim if (h == NULL) 811280304Sjkim return -1; 812142425Snectar 813280304Sjkim if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || 814280304Sjkim GetLastError() != ERROR_INSUFFICIENT_BUFFER) 815280304Sjkim return -1; 816142425Snectar 817280304Sjkim if (len > 512) 818280304Sjkim return -1; /* paranoia */ 819280304Sjkim len++, len &= ~1; /* paranoia */ 820280304Sjkim name = (WCHAR *)alloca(len + sizeof(WCHAR)); 821280304Sjkim if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) 822280304Sjkim return -1; 823142425Snectar 824280304Sjkim len++, len &= ~1; /* paranoia */ 825280304Sjkim name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ 826280304Sjkim# if 1 827280304Sjkim /* 828280304Sjkim * This doesn't cover "interactive" services [working with real 829280304Sjkim * WinSta0's] nor programs started non-interactively by Task Scheduler 830280304Sjkim * [those are working with SAWinSta]. 831280304Sjkim */ 832280304Sjkim if (wcsstr(name, L"Service-0x")) 833280304Sjkim return 1; 834280304Sjkim# else 835160814Ssimon /* This covers all non-interactive programs such as services. */ 836280304Sjkim if (!wcsstr(name, L"WinSta0")) 837280304Sjkim return 1; 838280304Sjkim# endif 839280304Sjkim else 840280304Sjkim return 0; 841160814Ssimon} 842280304Sjkim# else 843280304Sjkimint OPENSSL_isservice(void) 844280304Sjkim{ 845280304Sjkim return 0; 846280304Sjkim} 847280304Sjkim# endif 848142425Snectar 849280304Sjkimvoid OPENSSL_showfatal(const char *fmta, ...) 850280304Sjkim{ 851280304Sjkim va_list ap; 852280304Sjkim TCHAR buf[256]; 853280304Sjkim const TCHAR *fmt; 854280304Sjkim# ifdef STD_ERROR_HANDLE /* what a dirty trick! */ 855280304Sjkim HANDLE h; 856142425Snectar 857280304Sjkim if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && 858280304Sjkim GetFileType(h) != FILE_TYPE_UNKNOWN) { 859280304Sjkim /* must be console application */ 860280304Sjkim va_start(ap, fmta); 861280304Sjkim vfprintf(stderr, fmta, ap); 862280304Sjkim va_end(ap); 863280304Sjkim return; 864160814Ssimon } 865280304Sjkim# endif 866142425Snectar 867280304Sjkim if (sizeof(TCHAR) == sizeof(char)) 868280304Sjkim fmt = (const TCHAR *)fmta; 869280304Sjkim else 870280304Sjkim do { 871280304Sjkim int keepgoing; 872280304Sjkim size_t len_0 = strlen(fmta) + 1, i; 873280304Sjkim WCHAR *fmtw; 874142425Snectar 875280304Sjkim fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); 876280304Sjkim if (fmtw == NULL) { 877280304Sjkim fmt = (const TCHAR *)L"no stack?"; 878280304Sjkim break; 879280304Sjkim } 880280304Sjkim# ifndef OPENSSL_NO_MULTIBYTE 881280304Sjkim if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) 882280304Sjkim# endif 883280304Sjkim for (i = 0; i < len_0; i++) 884280304Sjkim fmtw[i] = (WCHAR)fmta[i]; 885142425Snectar 886280304Sjkim for (i = 0; i < len_0; i++) { 887280304Sjkim if (fmtw[i] == L'%') 888280304Sjkim do { 889280304Sjkim keepgoing = 0; 890280304Sjkim switch (fmtw[i + 1]) { 891280304Sjkim case L'0': 892280304Sjkim case L'1': 893280304Sjkim case L'2': 894280304Sjkim case L'3': 895280304Sjkim case L'4': 896280304Sjkim case L'5': 897280304Sjkim case L'6': 898280304Sjkim case L'7': 899280304Sjkim case L'8': 900280304Sjkim case L'9': 901280304Sjkim case L'.': 902280304Sjkim case L'*': 903280304Sjkim case L'-': 904280304Sjkim i++; 905280304Sjkim keepgoing = 1; 906280304Sjkim break; 907280304Sjkim case L's': 908280304Sjkim fmtw[i + 1] = L'S'; 909280304Sjkim break; 910280304Sjkim case L'S': 911280304Sjkim fmtw[i + 1] = L's'; 912280304Sjkim break; 913280304Sjkim case L'c': 914280304Sjkim fmtw[i + 1] = L'C'; 915280304Sjkim break; 916280304Sjkim case L'C': 917280304Sjkim fmtw[i + 1] = L'c'; 918280304Sjkim break; 919280304Sjkim } 920280304Sjkim } while (keepgoing); 921280304Sjkim } 922280304Sjkim fmt = (const TCHAR *)fmtw; 923280304Sjkim } while (0); 924142425Snectar 925280304Sjkim va_start(ap, fmta); 926280304Sjkim _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap); 927280304Sjkim buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0'); 928280304Sjkim va_end(ap); 929142425Snectar 930280304Sjkim# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 931160814Ssimon /* this -------------v--- guards NT-specific calls */ 932280304Sjkim if (check_winnt() && OPENSSL_isservice() > 0) { 933291721Sjkim HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); 934291721Sjkim 935291721Sjkim if (hEventLog != NULL) { 936291721Sjkim const TCHAR *pmsg = buf; 937291721Sjkim 938291721Sjkim if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 939291721Sjkim 1, 0, &pmsg, NULL)) { 940291721Sjkim#if defined(DEBUG) 941291721Sjkim /* 942291721Sjkim * We are in a situation where we tried to report a critical 943291721Sjkim * error and this failed for some reason. As a last resort, 944291721Sjkim * in debug builds, send output to the debugger or any other 945291721Sjkim * tool like DebugView which can monitor the output. 946291721Sjkim */ 947291721Sjkim OutputDebugString(pmsg); 948291721Sjkim#endif 949291721Sjkim } 950291721Sjkim 951291721Sjkim (void)DeregisterEventSource(hEventLog); 952291721Sjkim } 953280304Sjkim } else 954280304Sjkim# endif 955291721Sjkim MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); 956160814Ssimon} 957160814Ssimon#else 958280304Sjkimvoid OPENSSL_showfatal(const char *fmta, ...) 959280304Sjkim{ 960280304Sjkim va_list ap; 961142425Snectar 962280304Sjkim va_start(ap, fmta); 963280304Sjkim vfprintf(stderr, fmta, ap); 964280304Sjkim va_end(ap); 965160814Ssimon} 966280304Sjkim 967280304Sjkimint OPENSSL_isservice(void) 968280304Sjkim{ 969280304Sjkim return 0; 970280304Sjkim} 971160814Ssimon#endif 972142425Snectar 973280304Sjkimvoid OpenSSLDie(const char *file, int line, const char *assertion) 974280304Sjkim{ 975280304Sjkim OPENSSL_showfatal 976280304Sjkim ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line, 977280304Sjkim assertion); 978238405Sjkim#if !defined(_WIN32) || defined(__CYGWIN__) 979280304Sjkim abort(); 980238405Sjkim#else 981280304Sjkim /* 982280304Sjkim * Win32 abort() customarily shows a dialog, but we just did that... 983280304Sjkim */ 984280304Sjkim raise(SIGABRT); 985280304Sjkim _exit(3); 986238405Sjkim#endif 987280304Sjkim} 988142425Snectar 989280304Sjkimvoid *OPENSSL_stderr(void) 990280304Sjkim{ 991280304Sjkim return stderr; 992280304Sjkim} 993246772Sjkim 994246772Sjkimint CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) 995280304Sjkim{ 996280304Sjkim size_t i; 997280304Sjkim const unsigned char *a = in_a; 998280304Sjkim const unsigned char *b = in_b; 999280304Sjkim unsigned char x = 0; 1000246772Sjkim 1001280304Sjkim for (i = 0; i < len; i++) 1002280304Sjkim x |= a[i] ^ b[i]; 1003246772Sjkim 1004280304Sjkim return x; 1005280304Sjkim} 1006