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 10160814Ssimon * 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. 6155714Skris * 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). 6855714Skris * 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. 7555714Skris * 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 :-). 9055714Skris * 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)" 9355714Skris * 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. 10555714Skris * 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. 113160814Ssimon * 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) 12155714Skrisstatic 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 */ 127238405Sjkimstatic const char* const lock_names[CRYPTO_NUM_LOCKS] = 128238405Sjkim { 129238405Sjkim "<<ERROR>>", 130238405Sjkim "err", 131238405Sjkim "ex_data", 132238405Sjkim "x509", 133238405Sjkim "x509_info", 134238405Sjkim "x509_pkey", 135238405Sjkim "x509_crl", 136238405Sjkim "x509_req", 137238405Sjkim "dsa", 138238405Sjkim "rsa", 139238405Sjkim "evp_pkey", 140238405Sjkim "x509_store", 141238405Sjkim "ssl_ctx", 142238405Sjkim "ssl_cert", 143238405Sjkim "ssl_session", 144238405Sjkim "ssl_sess_cert", 145238405Sjkim "ssl", 146238405Sjkim "ssl_method", 147238405Sjkim "rand", 148238405Sjkim "rand2", 149238405Sjkim "debug_malloc", 150238405Sjkim "BIO", 151238405Sjkim "gethostbyname", 152238405Sjkim "getservbyname", 153238405Sjkim "readdir", 154238405Sjkim "RSA_blinding", 155238405Sjkim "dh", 156238405Sjkim "debug_malloc2", 157238405Sjkim "dso", 158238405Sjkim "dynlock", 159238405Sjkim "engine", 160238405Sjkim "ui", 161238405Sjkim "ecdsa", 162238405Sjkim "ec", 163238405Sjkim "ecdh", 164238405Sjkim "bn", 165238405Sjkim "ec_pre_comp", 166238405Sjkim "store", 167238405Sjkim "comp", 168238405Sjkim "fips", 169238405Sjkim "fips2", 170238405Sjkim#if CRYPTO_NUM_LOCKS != 41 171238405Sjkim# error "Inconsistency between crypto.h and cryptlib.c" 172238405Sjkim#endif 173238405Sjkim }; 174238405Sjkim 175238405Sjkim/* This is for applications to allocate new type names in the non-dynamic 176238405Sjkim array of lock names. These are numbered with positive numbers. */ 177238405Sjkimstatic STACK_OF(OPENSSL_STRING) *app_locks=NULL; 178238405Sjkim 179238405Sjkim/* For applications that want a more dynamic way of handling threads, the 180238405Sjkim following stack is used. These are externally numbered with negative 181238405Sjkim numbers. */ 182238405Sjkimstatic STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL; 183238405Sjkim 184238405Sjkim 18555714Skrisstatic void (MS_FAR *locking_callback)(int mode,int type, 186238405Sjkim const char *file,int line)=0; 18755714Skrisstatic int (MS_FAR *add_lock_callback)(int *pointer,int amount, 188238405Sjkim int type,const char *file,int line)=0; 189238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 190238405Sjkimstatic unsigned long (MS_FAR *id_callback)(void)=0; 191238405Sjkim#endif 192238405Sjkimstatic void (MS_FAR *threadid_callback)(CRYPTO_THREADID *)=0; 193238405Sjkimstatic struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback) 194238405Sjkim (const char *file,int line)=0; 195238405Sjkimstatic void (MS_FAR *dynlock_lock_callback)(int mode, 196238405Sjkim struct CRYPTO_dynlock_value *l, const char *file,int line)=0; 197238405Sjkimstatic void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l, 198238405Sjkim const char *file,int line)=0; 19968651Skris 200238405Sjkimint CRYPTO_get_new_lockid(char *name) 201238405Sjkim { 202238405Sjkim char *str; 203238405Sjkim int i; 204238405Sjkim 205238405Sjkim#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 206238405Sjkim /* A hack to make Visual C++ 5.0 work correctly when linking as 207238405Sjkim * a DLL using /MT. Without this, the application cannot use 208238405Sjkim * any floating point printf's. 209238405Sjkim * It also seems to be needed for Visual C 1.5 (win16) */ 210238405Sjkim SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; 211238405Sjkim#endif 212238405Sjkim 213238405Sjkim if ((app_locks == NULL) && ((app_locks=sk_OPENSSL_STRING_new_null()) == NULL)) 214238405Sjkim { 215238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 216238405Sjkim return(0); 217238405Sjkim } 218238405Sjkim if ((str=BUF_strdup(name)) == NULL) 219238405Sjkim { 220238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 221238405Sjkim return(0); 222238405Sjkim } 223238405Sjkim i=sk_OPENSSL_STRING_push(app_locks,str); 224238405Sjkim if (!i) 225238405Sjkim OPENSSL_free(str); 226238405Sjkim else 227238405Sjkim i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ 228238405Sjkim return(i); 229238405Sjkim } 230238405Sjkim 23155714Skrisint CRYPTO_num_locks(void) 23255714Skris { 23355714Skris return CRYPTO_NUM_LOCKS; 23455714Skris } 23555714Skris 236238405Sjkimint CRYPTO_get_new_dynlockid(void) 237238405Sjkim { 238238405Sjkim int i = 0; 239238405Sjkim CRYPTO_dynlock *pointer = NULL; 240238405Sjkim 241238405Sjkim if (dynlock_create_callback == NULL) 242238405Sjkim { 243238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK); 244238405Sjkim return(0); 245238405Sjkim } 246238405Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 247238405Sjkim if ((dyn_locks == NULL) 248238405Sjkim && ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL)) 249238405Sjkim { 250238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 251238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 252238405Sjkim return(0); 253238405Sjkim } 254238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 255238405Sjkim 256238405Sjkim pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock)); 257238405Sjkim if (pointer == NULL) 258238405Sjkim { 259238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 260238405Sjkim return(0); 261238405Sjkim } 262238405Sjkim pointer->references = 1; 263238405Sjkim pointer->data = dynlock_create_callback(__FILE__,__LINE__); 264238405Sjkim if (pointer->data == NULL) 265238405Sjkim { 266238405Sjkim OPENSSL_free(pointer); 267238405Sjkim CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 268238405Sjkim return(0); 269238405Sjkim } 270238405Sjkim 271238405Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 272238405Sjkim /* First, try to find an existing empty slot */ 273238405Sjkim i=sk_CRYPTO_dynlock_find(dyn_locks,NULL); 274238405Sjkim /* If there was none, push, thereby creating a new one */ 275238405Sjkim if (i == -1) 276238405Sjkim /* Since sk_push() returns the number of items on the 277238405Sjkim stack, not the location of the pushed item, we need 278238405Sjkim to transform the returned number into a position, 279238405Sjkim by decreasing it. */ 280238405Sjkim i=sk_CRYPTO_dynlock_push(dyn_locks,pointer) - 1; 281238405Sjkim else 282238405Sjkim /* If we found a place with a NULL pointer, put our pointer 283238405Sjkim in it. */ 284238405Sjkim (void)sk_CRYPTO_dynlock_set(dyn_locks,i,pointer); 285238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 286238405Sjkim 287238405Sjkim if (i == -1) 288238405Sjkim { 289238405Sjkim dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); 290238405Sjkim OPENSSL_free(pointer); 291238405Sjkim } 292238405Sjkim else 293238405Sjkim i += 1; /* to avoid 0 */ 294238405Sjkim return -i; 295238405Sjkim } 296238405Sjkim 297238405Sjkimvoid CRYPTO_destroy_dynlockid(int i) 298238405Sjkim { 299238405Sjkim CRYPTO_dynlock *pointer = NULL; 300238405Sjkim if (i) 301238405Sjkim i = -i-1; 302238405Sjkim if (dynlock_destroy_callback == NULL) 303238405Sjkim return; 304238405Sjkim 305238405Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 306238405Sjkim 307238405Sjkim if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) 308238405Sjkim { 309238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 310238405Sjkim return; 311238405Sjkim } 312238405Sjkim pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 313238405Sjkim if (pointer != NULL) 314238405Sjkim { 315238405Sjkim --pointer->references; 316238405Sjkim#ifdef REF_CHECK 317238405Sjkim if (pointer->references < 0) 318238405Sjkim { 319238405Sjkim fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n"); 320238405Sjkim abort(); 321238405Sjkim } 322238405Sjkim else 323238405Sjkim#endif 324238405Sjkim if (pointer->references <= 0) 325238405Sjkim { 326238405Sjkim (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); 327238405Sjkim } 328238405Sjkim else 329238405Sjkim pointer = NULL; 330238405Sjkim } 331238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 332238405Sjkim 333238405Sjkim if (pointer) 334238405Sjkim { 335238405Sjkim dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); 336238405Sjkim OPENSSL_free(pointer); 337238405Sjkim } 338238405Sjkim } 339238405Sjkim 340238405Sjkimstruct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i) 341238405Sjkim { 342238405Sjkim CRYPTO_dynlock *pointer = NULL; 343238405Sjkim if (i) 344238405Sjkim i = -i-1; 345238405Sjkim 346238405Sjkim CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 347238405Sjkim 348238405Sjkim if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks)) 349238405Sjkim pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 350238405Sjkim if (pointer) 351238405Sjkim pointer->references++; 352238405Sjkim 353238405Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 354238405Sjkim 355238405Sjkim if (pointer) 356238405Sjkim return pointer->data; 357238405Sjkim return NULL; 358238405Sjkim } 359238405Sjkim 360238405Sjkimstruct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void)) 361238405Sjkim (const char *file,int line) 362238405Sjkim { 363238405Sjkim return(dynlock_create_callback); 364238405Sjkim } 365238405Sjkim 366238405Sjkimvoid (*CRYPTO_get_dynlock_lock_callback(void))(int mode, 367238405Sjkim struct CRYPTO_dynlock_value *l, const char *file,int line) 368238405Sjkim { 369238405Sjkim return(dynlock_lock_callback); 370238405Sjkim } 371238405Sjkim 372238405Sjkimvoid (*CRYPTO_get_dynlock_destroy_callback(void)) 373238405Sjkim (struct CRYPTO_dynlock_value *l, const char *file,int line) 374238405Sjkim { 375238405Sjkim return(dynlock_destroy_callback); 376238405Sjkim } 377238405Sjkim 378238405Sjkimvoid CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func) 379238405Sjkim (const char *file, int line)) 380238405Sjkim { 381238405Sjkim dynlock_create_callback=func; 382238405Sjkim } 383238405Sjkim 384238405Sjkimvoid CRYPTO_set_dynlock_lock_callback(void (*func)(int mode, 385238405Sjkim struct CRYPTO_dynlock_value *l, const char *file, int line)) 386238405Sjkim { 387238405Sjkim dynlock_lock_callback=func; 388238405Sjkim } 389238405Sjkim 390238405Sjkimvoid CRYPTO_set_dynlock_destroy_callback(void (*func) 391238405Sjkim (struct CRYPTO_dynlock_value *l, const char *file, int line)) 392238405Sjkim { 393238405Sjkim dynlock_destroy_callback=func; 394238405Sjkim } 395238405Sjkim 396238405Sjkim 39755714Skrisvoid (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, 39855714Skris int line) 39955714Skris { 40055714Skris return(locking_callback); 40155714Skris } 40255714Skris 40355714Skrisint (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, 40455714Skris const char *file,int line) 40555714Skris { 40655714Skris return(add_lock_callback); 40755714Skris } 40855714Skris 40955714Skrisvoid CRYPTO_set_locking_callback(void (*func)(int mode,int type, 41055714Skris const char *file,int line)) 41155714Skris { 412238405Sjkim /* Calling this here ensures initialisation before any threads 413238405Sjkim * are started. 414238405Sjkim */ 415238405Sjkim OPENSSL_init(); 41655714Skris locking_callback=func; 41755714Skris } 41855714Skris 41955714Skrisvoid CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, 42055714Skris const char *file,int line)) 42155714Skris { 42255714Skris add_lock_callback=func; 42355714Skris } 42455714Skris 425238405Sjkim/* the memset() here and in set_pointer() seem overkill, but for the sake of 426238405Sjkim * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause two 427238405Sjkim * "equal" THREADID structs to not be memcmp()-identical. */ 428238405Sjkimvoid CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val) 429238405Sjkim { 430238405Sjkim memset(id, 0, sizeof(*id)); 431238405Sjkim id->val = val; 432238405Sjkim } 433238405Sjkim 434238405Sjkimstatic const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 }; 435238405Sjkimvoid CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr) 436238405Sjkim { 437238405Sjkim unsigned char *dest = (void *)&id->val; 438238405Sjkim unsigned int accum = 0; 439238405Sjkim unsigned char dnum = sizeof(id->val); 440238405Sjkim 441238405Sjkim memset(id, 0, sizeof(*id)); 442238405Sjkim id->ptr = ptr; 443238405Sjkim if (sizeof(id->val) >= sizeof(id->ptr)) 444238405Sjkim { 445238405Sjkim /* 'ptr' can be embedded in 'val' without loss of uniqueness */ 446238405Sjkim id->val = (unsigned long)id->ptr; 447238405Sjkim return; 448238405Sjkim } 449238405Sjkim /* hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a 450238405Sjkim * linear function over the bytes in 'ptr', the co-efficients of which 451238405Sjkim * are a sequence of low-primes (hash_coeffs is an 8-element cycle) - 452238405Sjkim * the starting prime for the sequence varies for each byte of 'val' 453238405Sjkim * (unique polynomials unless pointers are >64-bit). For added spice, 454238405Sjkim * the totals accumulate rather than restarting from zero, and the index 455238405Sjkim * of the 'val' byte is added each time (position dependence). If I was 456238405Sjkim * a black-belt, I'd scan big-endian pointers in reverse to give 457238405Sjkim * low-order bits more play, but this isn't crypto and I'd prefer nobody 458238405Sjkim * mistake it as such. Plus I'm lazy. */ 459238405Sjkim while (dnum--) 460238405Sjkim { 461238405Sjkim const unsigned char *src = (void *)&id->ptr; 462238405Sjkim unsigned char snum = sizeof(id->ptr); 463238405Sjkim while (snum--) 464238405Sjkim accum += *(src++) * hash_coeffs[(snum + dnum) & 7]; 465238405Sjkim accum += dnum; 466238405Sjkim *(dest++) = accum & 255; 467238405Sjkim } 468238405Sjkim } 469238405Sjkim 470238405Sjkimint CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *)) 471238405Sjkim { 472238405Sjkim if (threadid_callback) 473238405Sjkim return 0; 474238405Sjkim threadid_callback = func; 475238405Sjkim return 1; 476238405Sjkim } 477238405Sjkim 478238405Sjkimvoid (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *) 479238405Sjkim { 480238405Sjkim return threadid_callback; 481238405Sjkim } 482238405Sjkim 483238405Sjkimvoid CRYPTO_THREADID_current(CRYPTO_THREADID *id) 484238405Sjkim { 485238405Sjkim if (threadid_callback) 486238405Sjkim { 487238405Sjkim threadid_callback(id); 488238405Sjkim return; 489238405Sjkim } 490238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 491238405Sjkim /* If the deprecated callback was set, fall back to that */ 492238405Sjkim if (id_callback) 493238405Sjkim { 494238405Sjkim CRYPTO_THREADID_set_numeric(id, id_callback()); 495238405Sjkim return; 496238405Sjkim } 497238405Sjkim#endif 498238405Sjkim /* Else pick a backup */ 499238405Sjkim#ifdef OPENSSL_SYS_WIN16 500238405Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask()); 501238405Sjkim#elif defined(OPENSSL_SYS_WIN32) 502238405Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId()); 503238405Sjkim#elif defined(OPENSSL_SYS_BEOS) 504238405Sjkim CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL)); 505238405Sjkim#else 506238405Sjkim /* For everything else, default to using the address of 'errno' */ 507246772Sjkim CRYPTO_THREADID_set_pointer(id, (void*)&errno); 508238405Sjkim#endif 509238405Sjkim } 510238405Sjkim 511238405Sjkimint CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b) 512238405Sjkim { 513238405Sjkim return memcmp(a, b, sizeof(*a)); 514238405Sjkim } 515238405Sjkim 516238405Sjkimvoid CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src) 517238405Sjkim { 518238405Sjkim memcpy(dest, src, sizeof(*src)); 519238405Sjkim } 520238405Sjkim 521238405Sjkimunsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id) 522238405Sjkim { 523238405Sjkim return id->val; 524238405Sjkim } 525238405Sjkim 526238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 52755714Skrisunsigned long (*CRYPTO_get_id_callback(void))(void) 52855714Skris { 52955714Skris return(id_callback); 53055714Skris } 53155714Skris 53255714Skrisvoid CRYPTO_set_id_callback(unsigned long (*func)(void)) 53355714Skris { 53455714Skris id_callback=func; 53555714Skris } 53655714Skris 53755714Skrisunsigned long CRYPTO_thread_id(void) 53855714Skris { 53955714Skris unsigned long ret=0; 54055714Skris 54155714Skris if (id_callback == NULL) 54255714Skris { 543109998Smarkm#ifdef OPENSSL_SYS_WIN16 54455714Skris ret=(unsigned long)GetCurrentTask(); 545109998Smarkm#elif defined(OPENSSL_SYS_WIN32) 54655714Skris ret=(unsigned long)GetCurrentThreadId(); 54759191Skris#elif defined(GETPID_IS_MEANINGLESS) 54855714Skris ret=1L; 549238405Sjkim#elif defined(OPENSSL_SYS_BEOS) 550238405Sjkim ret=(unsigned long)find_thread(NULL); 55155714Skris#else 55255714Skris ret=(unsigned long)getpid(); 55355714Skris#endif 55455714Skris } 55555714Skris else 55655714Skris ret=id_callback(); 55755714Skris return(ret); 55855714Skris } 559238405Sjkim#endif 56055714Skris 56155714Skrisvoid CRYPTO_lock(int mode, int type, const char *file, int line) 56255714Skris { 56355714Skris#ifdef LOCK_DEBUG 56455714Skris { 565238405Sjkim CRYPTO_THREADID id; 56655714Skris char *rw_text,*operation_text; 56755714Skris 56855714Skris if (mode & CRYPTO_LOCK) 56955714Skris operation_text="lock "; 57055714Skris else if (mode & CRYPTO_UNLOCK) 57155714Skris operation_text="unlock"; 57255714Skris else 57355714Skris operation_text="ERROR "; 57455714Skris 57555714Skris if (mode & CRYPTO_READ) 57655714Skris rw_text="r"; 57755714Skris else if (mode & CRYPTO_WRITE) 57855714Skris rw_text="w"; 57955714Skris else 58055714Skris rw_text="ERROR"; 58155714Skris 582238405Sjkim CRYPTO_THREADID_current(&id); 58355714Skris fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", 584238405Sjkim CRYPTO_THREADID_hash(&id), rw_text, operation_text, 58555714Skris CRYPTO_get_lock_name(type), file, line); 58655714Skris } 58755714Skris#endif 58868651Skris if (type < 0) 58968651Skris { 590238405Sjkim if (dynlock_lock_callback != NULL) 591238405Sjkim { 592238405Sjkim struct CRYPTO_dynlock_value *pointer 593238405Sjkim = CRYPTO_get_dynlock_value(type); 594238405Sjkim 595238405Sjkim OPENSSL_assert(pointer != NULL); 596238405Sjkim 597238405Sjkim dynlock_lock_callback(mode, pointer, file, line); 598238405Sjkim 599238405Sjkim CRYPTO_destroy_dynlockid(type); 600238405Sjkim } 60168651Skris } 60268651Skris else 60368651Skris if (locking_callback != NULL) 60468651Skris locking_callback(mode,type,file,line); 60555714Skris } 60655714Skris 60755714Skrisint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 60855714Skris int line) 60955714Skris { 61068651Skris int ret = 0; 61155714Skris 61255714Skris if (add_lock_callback != NULL) 61355714Skris { 61455714Skris#ifdef LOCK_DEBUG 61555714Skris int before= *pointer; 61655714Skris#endif 61755714Skris 61855714Skris ret=add_lock_callback(pointer,amount,type,file,line); 61955714Skris#ifdef LOCK_DEBUG 620238405Sjkim { 621238405Sjkim CRYPTO_THREADID id; 622238405Sjkim CRYPTO_THREADID_current(&id); 62355714Skris fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 624238405Sjkim CRYPTO_THREADID_hash(&id), before,amount,ret, 62555714Skris CRYPTO_get_lock_name(type), 62655714Skris file,line); 627238405Sjkim } 62855714Skris#endif 62955714Skris } 63055714Skris else 63155714Skris { 63255714Skris CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); 63355714Skris 63455714Skris ret= *pointer+amount; 63555714Skris#ifdef LOCK_DEBUG 636238405Sjkim { 637238405Sjkim CRYPTO_THREADID id; 638238405Sjkim CRYPTO_THREADID_current(&id); 63955714Skris fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 640238405Sjkim CRYPTO_THREADID_hash(&id), 64155714Skris *pointer,amount,ret, 64255714Skris CRYPTO_get_lock_name(type), 64355714Skris file,line); 644238405Sjkim } 64555714Skris#endif 64655714Skris *pointer=ret; 64755714Skris CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); 64855714Skris } 64955714Skris return(ret); 65055714Skris } 65155714Skris 652238405Sjkimconst char *CRYPTO_get_lock_name(int type) 653238405Sjkim { 654238405Sjkim if (type < 0) 655238405Sjkim return("dynamic"); 656238405Sjkim else if (type < CRYPTO_NUM_LOCKS) 657238405Sjkim return(lock_names[type]); 658238405Sjkim else if (type-CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks)) 659238405Sjkim return("ERROR"); 660238405Sjkim else 661238405Sjkim return(sk_OPENSSL_STRING_value(app_locks,type-CRYPTO_NUM_LOCKS)); 662238405Sjkim } 663238405Sjkim 664160814Ssimon#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 665160814Ssimon defined(__INTEL__) || \ 666194206Ssimon defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) 66755714Skris 668238405Sjkimunsigned int OPENSSL_ia32cap_P[2]; 669238405Sjkimunsigned long *OPENSSL_ia32cap_loc(void) 670238405Sjkim{ if (sizeof(long)==4) 671238405Sjkim /* 672238405Sjkim * If 32-bit application pulls address of OPENSSL_ia32cap_P[0] 673238405Sjkim * clear second element to maintain the illusion that vector 674238405Sjkim * is 32-bit. 675238405Sjkim */ 676238405Sjkim OPENSSL_ia32cap_P[1]=0; 677238405Sjkim return (unsigned long *)OPENSSL_ia32cap_P; 678238405Sjkim} 679160814Ssimon 680160814Ssimon#if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) 681160814Ssimon#define OPENSSL_CPUID_SETUP 682238405Sjkim#if defined(_WIN32) 683238405Sjkimtypedef unsigned __int64 IA32CAP; 684238405Sjkim#else 685238405Sjkimtypedef unsigned long long IA32CAP; 686238405Sjkim#endif 687160814Ssimonvoid OPENSSL_cpuid_setup(void) 688160814Ssimon{ static int trigger=0; 689238405Sjkim IA32CAP OPENSSL_ia32_cpuid(void); 690238405Sjkim IA32CAP vec; 691160814Ssimon char *env; 692160814Ssimon 693160814Ssimon if (trigger) return; 694160814Ssimon 695160814Ssimon trigger=1; 696238405Sjkim if ((env=getenv("OPENSSL_ia32cap"))) { 697238405Sjkim int off = (env[0]=='~')?1:0; 698238405Sjkim#if defined(_WIN32) 699238405Sjkim if (!sscanf(env+off,"%I64i",&vec)) vec = strtoul(env+off,NULL,0); 700238405Sjkim#else 701238405Sjkim if (!sscanf(env+off,"%lli",(long long *)&vec)) vec = strtoul(env+off,NULL,0); 702238405Sjkim#endif 703238405Sjkim if (off) vec = OPENSSL_ia32_cpuid()&~vec; 704238405Sjkim } 705160814Ssimon else 706238405Sjkim vec = OPENSSL_ia32_cpuid(); 707246772Sjkim 708160814Ssimon /* 709160814Ssimon * |(1<<10) sets a reserved bit to signal that variable 710160814Ssimon * was initialized already... This is to avoid interference 711160814Ssimon * with cpuid snippets in ELF .init segment. 712160814Ssimon */ 713238405Sjkim OPENSSL_ia32cap_P[0] = (unsigned int)vec|(1<<10); 714238405Sjkim OPENSSL_ia32cap_P[1] = (unsigned int)(vec>>32); 715160814Ssimon} 716160814Ssimon#endif 717160814Ssimon 718160814Ssimon#else 719160814Ssimonunsigned long *OPENSSL_ia32cap_loc(void) { return NULL; } 720160814Ssimon#endif 721160814Ssimonint OPENSSL_NONPIC_relocated = 0; 722238405Sjkim#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) 723160814Ssimonvoid OPENSSL_cpuid_setup(void) {} 724160814Ssimon#endif 725160814Ssimon 726160814Ssimon#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL) 727160814Ssimon#ifdef __CYGWIN__ 728160814Ssimon/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */ 729160814Ssimon#include <windows.h> 730238405Sjkim/* this has side-effect of _WIN32 getting defined, which otherwise 731238405Sjkim * is mutually exclusive with __CYGWIN__... */ 732160814Ssimon#endif 733160814Ssimon 73455714Skris/* All we really need to do is remove the 'error' state when a thread 73555714Skris * detaches */ 73655714Skris 737160814SsimonBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, 73855714Skris LPVOID lpvReserved) 73955714Skris { 74055714Skris switch(fdwReason) 74155714Skris { 74255714Skris case DLL_PROCESS_ATTACH: 743160814Ssimon OPENSSL_cpuid_setup(); 744160814Ssimon#if defined(_WIN32_WINNT) 745160814Ssimon { 746160814Ssimon IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)hinstDLL; 747160814Ssimon IMAGE_NT_HEADERS *nt_headers; 748160814Ssimon 749160814Ssimon if (dos_header->e_magic==IMAGE_DOS_SIGNATURE) 750160814Ssimon { 751160814Ssimon nt_headers = (IMAGE_NT_HEADERS *)((char *)dos_header 752160814Ssimon + dos_header->e_lfanew); 753160814Ssimon if (nt_headers->Signature==IMAGE_NT_SIGNATURE && 754160814Ssimon hinstDLL!=(HINSTANCE)(nt_headers->OptionalHeader.ImageBase)) 755160814Ssimon OPENSSL_NONPIC_relocated=1; 756160814Ssimon } 757160814Ssimon } 758160814Ssimon#endif 75955714Skris break; 76055714Skris case DLL_THREAD_ATTACH: 76155714Skris break; 76255714Skris case DLL_THREAD_DETACH: 76355714Skris break; 76455714Skris case DLL_PROCESS_DETACH: 76555714Skris break; 76655714Skris } 76755714Skris return(TRUE); 76855714Skris } 76955714Skris#endif 77055714Skris 771160814Ssimon#if defined(_WIN32) && !defined(__CYGWIN__) 772160814Ssimon#include <tchar.h> 773238405Sjkim#include <signal.h> 774238405Sjkim#ifdef __WATCOMC__ 775238405Sjkim#if defined(_UNICODE) || defined(__UNICODE__) 776238405Sjkim#define _vsntprintf _vsnwprintf 777238405Sjkim#else 778238405Sjkim#define _vsntprintf _vsnprintf 779238405Sjkim#endif 780238405Sjkim#endif 781238405Sjkim#ifdef _MSC_VER 782238405Sjkim#define alloca _alloca 783238405Sjkim#endif 784109998Smarkm 785160814Ssimon#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 786160814Ssimonint OPENSSL_isservice(void) 787160814Ssimon{ HWINSTA h; 788160814Ssimon DWORD len; 789160814Ssimon WCHAR *name; 790238405Sjkim static union { void *p; int (*f)(void); } _OPENSSL_isservice = { NULL }; 791142425Snectar 792238405Sjkim if (_OPENSSL_isservice.p == NULL) { 793238405Sjkim HANDLE h = GetModuleHandle(NULL); 794238405Sjkim if (h != NULL) 795238405Sjkim _OPENSSL_isservice.p = GetProcAddress(h,"_OPENSSL_isservice"); 796238405Sjkim if (_OPENSSL_isservice.p == NULL) 797238405Sjkim _OPENSSL_isservice.p = (void *)-1; 798238405Sjkim } 799238405Sjkim 800238405Sjkim if (_OPENSSL_isservice.p != (void *)-1) 801238405Sjkim return (*_OPENSSL_isservice.f)(); 802238405Sjkim 803160814Ssimon (void)GetDesktopWindow(); /* return value is ignored */ 804142425Snectar 805160814Ssimon h = GetProcessWindowStation(); 806160814Ssimon if (h==NULL) return -1; 807142425Snectar 808160814Ssimon if (GetUserObjectInformationW (h,UOI_NAME,NULL,0,&len) || 809160814Ssimon GetLastError() != ERROR_INSUFFICIENT_BUFFER) 810160814Ssimon return -1; 811142425Snectar 812160814Ssimon if (len>512) return -1; /* paranoia */ 813160814Ssimon len++,len&=~1; /* paranoia */ 814160814Ssimon name=(WCHAR *)alloca(len+sizeof(WCHAR)); 815160814Ssimon if (!GetUserObjectInformationW (h,UOI_NAME,name,len,&len)) 816160814Ssimon return -1; 817142425Snectar 818160814Ssimon len++,len&=~1; /* paranoia */ 819160814Ssimon name[len/sizeof(WCHAR)]=L'\0'; /* paranoia */ 820160814Ssimon#if 1 821160814Ssimon /* This doesn't cover "interactive" services [working with real 822160814Ssimon * WinSta0's] nor programs started non-interactively by Task 823160814Ssimon * Scheduler [those are working with SAWinSta]. */ 824160814Ssimon if (wcsstr(name,L"Service-0x")) return 1; 825160814Ssimon#else 826160814Ssimon /* This covers all non-interactive programs such as services. */ 827160814Ssimon if (!wcsstr(name,L"WinSta0")) return 1; 828160814Ssimon#endif 829160814Ssimon else return 0; 830160814Ssimon} 831160814Ssimon#else 832160814Ssimonint OPENSSL_isservice(void) { return 0; } 833160814Ssimon#endif 834142425Snectar 835160814Ssimonvoid OPENSSL_showfatal (const char *fmta,...) 836160814Ssimon{ va_list ap; 837160814Ssimon TCHAR buf[256]; 838160814Ssimon const TCHAR *fmt; 839160814Ssimon#ifdef STD_ERROR_HANDLE /* what a dirty trick! */ 840160814Ssimon HANDLE h; 841142425Snectar 842160814Ssimon if ((h=GetStdHandle(STD_ERROR_HANDLE)) != NULL && 843160814Ssimon GetFileType(h)!=FILE_TYPE_UNKNOWN) 844160814Ssimon { /* must be console application */ 845160814Ssimon va_start (ap,fmta); 846160814Ssimon vfprintf (stderr,fmta,ap); 847160814Ssimon va_end (ap); 848160814Ssimon return; 849160814Ssimon } 850160814Ssimon#endif 851142425Snectar 852160814Ssimon if (sizeof(TCHAR)==sizeof(char)) 853160814Ssimon fmt=(const TCHAR *)fmta; 854160814Ssimon else do 855160814Ssimon { int keepgoing; 856160814Ssimon size_t len_0=strlen(fmta)+1,i; 857160814Ssimon WCHAR *fmtw; 858142425Snectar 859238405Sjkim fmtw = (WCHAR *)alloca(len_0*sizeof(WCHAR)); 860160814Ssimon if (fmtw == NULL) { fmt=(const TCHAR *)L"no stack?"; break; } 861142425Snectar 862160814Ssimon#ifndef OPENSSL_NO_MULTIBYTE 863160814Ssimon if (!MultiByteToWideChar(CP_ACP,0,fmta,len_0,fmtw,len_0)) 864160814Ssimon#endif 865160814Ssimon for (i=0;i<len_0;i++) fmtw[i]=(WCHAR)fmta[i]; 866142425Snectar 867160814Ssimon for (i=0;i<len_0;i++) 868160814Ssimon { if (fmtw[i]==L'%') do 869160814Ssimon { keepgoing=0; 870160814Ssimon switch (fmtw[i+1]) 871160814Ssimon { case L'0': case L'1': case L'2': case L'3': case L'4': 872160814Ssimon case L'5': case L'6': case L'7': case L'8': case L'9': 873160814Ssimon case L'.': case L'*': 874160814Ssimon case L'-': i++; keepgoing=1; break; 875160814Ssimon case L's': fmtw[i+1]=L'S'; break; 876160814Ssimon case L'S': fmtw[i+1]=L's'; break; 877160814Ssimon case L'c': fmtw[i+1]=L'C'; break; 878160814Ssimon case L'C': fmtw[i+1]=L'c'; break; 879142425Snectar } 880160814Ssimon } while (keepgoing); 881142425Snectar } 882160814Ssimon fmt = (const TCHAR *)fmtw; 883160814Ssimon } while (0); 884142425Snectar 885160814Ssimon va_start (ap,fmta); 886160814Ssimon _vsntprintf (buf,sizeof(buf)/sizeof(TCHAR)-1,fmt,ap); 887160814Ssimon buf [sizeof(buf)/sizeof(TCHAR)-1] = _T('\0'); 888160814Ssimon va_end (ap); 889142425Snectar 890160814Ssimon#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 891160814Ssimon /* this -------------v--- guards NT-specific calls */ 892279264Sdelphij if (check_winnt() && OPENSSL_isservice() > 0) 893160814Ssimon { HANDLE h = RegisterEventSource(0,_T("OPENSSL")); 894160814Ssimon const TCHAR *pmsg=buf; 895160814Ssimon ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0); 896160814Ssimon DeregisterEventSource(h); 897160814Ssimon } 898160814Ssimon else 899160814Ssimon#endif 900160814Ssimon MessageBox (NULL,buf,_T("OpenSSL: FATAL"),MB_OK|MB_ICONSTOP); 901160814Ssimon} 902160814Ssimon#else 903160814Ssimonvoid OPENSSL_showfatal (const char *fmta,...) 904160814Ssimon{ va_list ap; 905142425Snectar 906160814Ssimon va_start (ap,fmta); 907160814Ssimon vfprintf (stderr,fmta,ap); 908160814Ssimon va_end (ap); 909160814Ssimon} 910160814Ssimonint OPENSSL_isservice (void) { return 0; } 911160814Ssimon#endif 912142425Snectar 913160814Ssimonvoid OpenSSLDie(const char *file,int line,const char *assertion) 914142425Snectar { 915160814Ssimon OPENSSL_showfatal( 916160814Ssimon "%s(%d): OpenSSL internal error, assertion failed: %s\n", 917160814Ssimon file,line,assertion); 918238405Sjkim#if !defined(_WIN32) || defined(__CYGWIN__) 919160814Ssimon abort(); 920238405Sjkim#else 921238405Sjkim /* Win32 abort() customarily shows a dialog, but we just did that... */ 922238405Sjkim raise(SIGABRT); 923238405Sjkim _exit(3); 924238405Sjkim#endif 925142425Snectar } 926142425Snectar 927160814Ssimonvoid *OPENSSL_stderr(void) { return stderr; } 928246772Sjkim 929246772Sjkimint CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) 930246772Sjkim { 931246772Sjkim size_t i; 932246772Sjkim const unsigned char *a = in_a; 933246772Sjkim const unsigned char *b = in_b; 934246772Sjkim unsigned char x = 0; 935246772Sjkim 936246772Sjkim for (i = 0; i < len; i++) 937246772Sjkim x |= a[i] ^ b[i]; 938246772Sjkim 939246772Sjkim return x; 940246772Sjkim } 941