1*0Sstevel@tonic-gate /* crypto/cryptlib.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include <string.h> 61*0Sstevel@tonic-gate #include "cryptlib.h" 62*0Sstevel@tonic-gate #include <openssl/crypto.h> 63*0Sstevel@tonic-gate #include <openssl/safestack.h> 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 66*0Sstevel@tonic-gate static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ 67*0Sstevel@tonic-gate #endif 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate DECLARE_STACK_OF(CRYPTO_dynlock) 70*0Sstevel@tonic-gate IMPLEMENT_STACK_OF(CRYPTO_dynlock) 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* real #defines in crypto.h, keep these upto date */ 73*0Sstevel@tonic-gate static const char* lock_names[CRYPTO_NUM_LOCKS] = 74*0Sstevel@tonic-gate { 75*0Sstevel@tonic-gate "<<ERROR>>", 76*0Sstevel@tonic-gate "err", 77*0Sstevel@tonic-gate "ex_data", 78*0Sstevel@tonic-gate "x509", 79*0Sstevel@tonic-gate "x509_info", 80*0Sstevel@tonic-gate "x509_pkey", 81*0Sstevel@tonic-gate "x509_crl", 82*0Sstevel@tonic-gate "x509_req", 83*0Sstevel@tonic-gate "dsa", 84*0Sstevel@tonic-gate "rsa", 85*0Sstevel@tonic-gate "evp_pkey", 86*0Sstevel@tonic-gate "x509_store", 87*0Sstevel@tonic-gate "ssl_ctx", 88*0Sstevel@tonic-gate "ssl_cert", 89*0Sstevel@tonic-gate "ssl_session", 90*0Sstevel@tonic-gate "ssl_sess_cert", 91*0Sstevel@tonic-gate "ssl", 92*0Sstevel@tonic-gate "ssl_method", 93*0Sstevel@tonic-gate "rand", 94*0Sstevel@tonic-gate "rand2", 95*0Sstevel@tonic-gate "debug_malloc", 96*0Sstevel@tonic-gate "BIO", 97*0Sstevel@tonic-gate "gethostbyname", 98*0Sstevel@tonic-gate "getservbyname", 99*0Sstevel@tonic-gate "readdir", 100*0Sstevel@tonic-gate "RSA_blinding", 101*0Sstevel@tonic-gate "dh", 102*0Sstevel@tonic-gate "debug_malloc2", 103*0Sstevel@tonic-gate "dso", 104*0Sstevel@tonic-gate "dynlock", 105*0Sstevel@tonic-gate "engine", 106*0Sstevel@tonic-gate "ui", 107*0Sstevel@tonic-gate "hwcrhk", /* This is a HACK which will disappear in 0.9.8 */ 108*0Sstevel@tonic-gate #if CRYPTO_NUM_LOCKS != 33 109*0Sstevel@tonic-gate # error "Inconsistency between crypto.h and cryptlib.c" 110*0Sstevel@tonic-gate #endif 111*0Sstevel@tonic-gate }; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* This is for applications to allocate new type names in the non-dynamic 114*0Sstevel@tonic-gate array of lock names. These are numbered with positive numbers. */ 115*0Sstevel@tonic-gate static STACK *app_locks=NULL; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate /* For applications that want a more dynamic way of handling threads, the 118*0Sstevel@tonic-gate following stack is used. These are externally numbered with negative 119*0Sstevel@tonic-gate numbers. */ 120*0Sstevel@tonic-gate static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL; 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate static void (MS_FAR *locking_callback)(int mode,int type, 124*0Sstevel@tonic-gate const char *file,int line)=NULL; 125*0Sstevel@tonic-gate static int (MS_FAR *add_lock_callback)(int *pointer,int amount, 126*0Sstevel@tonic-gate int type,const char *file,int line)=NULL; 127*0Sstevel@tonic-gate static unsigned long (MS_FAR *id_callback)(void)=NULL; 128*0Sstevel@tonic-gate static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback) 129*0Sstevel@tonic-gate (const char *file,int line)=NULL; 130*0Sstevel@tonic-gate static void (MS_FAR *dynlock_lock_callback)(int mode, 131*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *l, const char *file,int line)=NULL; 132*0Sstevel@tonic-gate static void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l, 133*0Sstevel@tonic-gate const char *file,int line)=NULL; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate int CRYPTO_get_new_lockid(char *name) 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate char *str; 138*0Sstevel@tonic-gate int i; 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) 141*0Sstevel@tonic-gate /* A hack to make Visual C++ 5.0 work correctly when linking as 142*0Sstevel@tonic-gate * a DLL using /MT. Without this, the application cannot use 143*0Sstevel@tonic-gate * and floating point printf's. 144*0Sstevel@tonic-gate * It also seems to be needed for Visual C 1.5 (win16) */ 145*0Sstevel@tonic-gate SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; 146*0Sstevel@tonic-gate #endif 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL)) 149*0Sstevel@tonic-gate { 150*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 151*0Sstevel@tonic-gate return(0); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate if ((str=BUF_strdup(name)) == NULL) 154*0Sstevel@tonic-gate { 155*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 156*0Sstevel@tonic-gate return(0); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate i=sk_push(app_locks,str); 159*0Sstevel@tonic-gate if (!i) 160*0Sstevel@tonic-gate OPENSSL_free(str); 161*0Sstevel@tonic-gate else 162*0Sstevel@tonic-gate i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ 163*0Sstevel@tonic-gate return(i); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate int CRYPTO_num_locks(void) 167*0Sstevel@tonic-gate { 168*0Sstevel@tonic-gate return CRYPTO_NUM_LOCKS; 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate int CRYPTO_get_new_dynlockid(void) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate int i = 0; 174*0Sstevel@tonic-gate CRYPTO_dynlock *pointer = NULL; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate if (dynlock_create_callback == NULL) 177*0Sstevel@tonic-gate { 178*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK); 179*0Sstevel@tonic-gate return(0); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 182*0Sstevel@tonic-gate if ((dyn_locks == NULL) 183*0Sstevel@tonic-gate && ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL)) 184*0Sstevel@tonic-gate { 185*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 186*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 187*0Sstevel@tonic-gate return(0); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock)); 192*0Sstevel@tonic-gate if (pointer == NULL) 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 195*0Sstevel@tonic-gate return(0); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate pointer->references = 1; 198*0Sstevel@tonic-gate pointer->data = dynlock_create_callback(__FILE__,__LINE__); 199*0Sstevel@tonic-gate if (pointer->data == NULL) 200*0Sstevel@tonic-gate { 201*0Sstevel@tonic-gate OPENSSL_free(pointer); 202*0Sstevel@tonic-gate CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); 203*0Sstevel@tonic-gate return(0); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 207*0Sstevel@tonic-gate /* First, try to find an existing empty slot */ 208*0Sstevel@tonic-gate i=sk_CRYPTO_dynlock_find(dyn_locks,NULL); 209*0Sstevel@tonic-gate /* If there was none, push, thereby creating a new one */ 210*0Sstevel@tonic-gate if (i == -1) 211*0Sstevel@tonic-gate /* Since sk_push() returns the number of items on the 212*0Sstevel@tonic-gate stack, not the location of the pushed item, we need 213*0Sstevel@tonic-gate to transform the returned number into a position, 214*0Sstevel@tonic-gate by decreasing it. */ 215*0Sstevel@tonic-gate i=sk_CRYPTO_dynlock_push(dyn_locks,pointer) - 1; 216*0Sstevel@tonic-gate else 217*0Sstevel@tonic-gate /* If we found a place with a NULL pointer, put our pointer 218*0Sstevel@tonic-gate in it. */ 219*0Sstevel@tonic-gate sk_CRYPTO_dynlock_set(dyn_locks,i,pointer); 220*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate if (i == -1) 223*0Sstevel@tonic-gate { 224*0Sstevel@tonic-gate dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); 225*0Sstevel@tonic-gate OPENSSL_free(pointer); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate else 228*0Sstevel@tonic-gate i += 1; /* to avoid 0 */ 229*0Sstevel@tonic-gate return -i; 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate void CRYPTO_destroy_dynlockid(int i) 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate CRYPTO_dynlock *pointer = NULL; 235*0Sstevel@tonic-gate if (i) 236*0Sstevel@tonic-gate i = -i-1; 237*0Sstevel@tonic-gate if (dynlock_destroy_callback == NULL) 238*0Sstevel@tonic-gate return; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) 243*0Sstevel@tonic-gate { 244*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 245*0Sstevel@tonic-gate return; 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 248*0Sstevel@tonic-gate if (pointer != NULL) 249*0Sstevel@tonic-gate { 250*0Sstevel@tonic-gate --pointer->references; 251*0Sstevel@tonic-gate #ifdef REF_CHECK 252*0Sstevel@tonic-gate if (pointer->references < 0) 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n"); 255*0Sstevel@tonic-gate abort(); 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate else 258*0Sstevel@tonic-gate #endif 259*0Sstevel@tonic-gate if (pointer->references <= 0) 260*0Sstevel@tonic-gate { 261*0Sstevel@tonic-gate sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); 262*0Sstevel@tonic-gate } 263*0Sstevel@tonic-gate else 264*0Sstevel@tonic-gate pointer = NULL; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate if (pointer) 269*0Sstevel@tonic-gate { 270*0Sstevel@tonic-gate dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); 271*0Sstevel@tonic-gate OPENSSL_free(pointer); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i) 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate CRYPTO_dynlock *pointer = NULL; 278*0Sstevel@tonic-gate if (i) 279*0Sstevel@tonic-gate i = -i-1; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks)) 284*0Sstevel@tonic-gate pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); 285*0Sstevel@tonic-gate if (pointer) 286*0Sstevel@tonic-gate pointer->references++; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate if (pointer) 291*0Sstevel@tonic-gate return pointer->data; 292*0Sstevel@tonic-gate return NULL; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate 295*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void)) 296*0Sstevel@tonic-gate (const char *file,int line) 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate return(dynlock_create_callback); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, 302*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *l, const char *file,int line) 303*0Sstevel@tonic-gate { 304*0Sstevel@tonic-gate return(dynlock_lock_callback); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate void (*CRYPTO_get_dynlock_destroy_callback(void)) 308*0Sstevel@tonic-gate (struct CRYPTO_dynlock_value *l, const char *file,int line) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate return(dynlock_destroy_callback); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func) 314*0Sstevel@tonic-gate (const char *file, int line)) 315*0Sstevel@tonic-gate { 316*0Sstevel@tonic-gate dynlock_create_callback=func; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate void CRYPTO_set_dynlock_lock_callback(void (*func)(int mode, 320*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *l, const char *file, int line)) 321*0Sstevel@tonic-gate { 322*0Sstevel@tonic-gate dynlock_lock_callback=func; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate void CRYPTO_set_dynlock_destroy_callback(void (*func) 326*0Sstevel@tonic-gate (struct CRYPTO_dynlock_value *l, const char *file, int line)) 327*0Sstevel@tonic-gate { 328*0Sstevel@tonic-gate dynlock_destroy_callback=func; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, 333*0Sstevel@tonic-gate int line) 334*0Sstevel@tonic-gate { 335*0Sstevel@tonic-gate return(locking_callback); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, 339*0Sstevel@tonic-gate const char *file,int line) 340*0Sstevel@tonic-gate { 341*0Sstevel@tonic-gate return(add_lock_callback); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate void CRYPTO_set_locking_callback(void (*func)(int mode,int type, 345*0Sstevel@tonic-gate const char *file,int line)) 346*0Sstevel@tonic-gate { 347*0Sstevel@tonic-gate locking_callback=func; 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, 351*0Sstevel@tonic-gate const char *file,int line)) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate add_lock_callback=func; 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate unsigned long (*CRYPTO_get_id_callback(void))(void) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate return(id_callback); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate void CRYPTO_set_id_callback(unsigned long (*func)(void)) 362*0Sstevel@tonic-gate { 363*0Sstevel@tonic-gate id_callback=func; 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate unsigned long CRYPTO_thread_id(void) 367*0Sstevel@tonic-gate { 368*0Sstevel@tonic-gate unsigned long ret=0; 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate if (id_callback == NULL) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN16 373*0Sstevel@tonic-gate ret=(unsigned long)GetCurrentTask(); 374*0Sstevel@tonic-gate #elif defined(OPENSSL_SYS_WIN32) 375*0Sstevel@tonic-gate ret=(unsigned long)GetCurrentThreadId(); 376*0Sstevel@tonic-gate #elif defined(GETPID_IS_MEANINGLESS) 377*0Sstevel@tonic-gate ret=1L; 378*0Sstevel@tonic-gate #else 379*0Sstevel@tonic-gate ret=(unsigned long)getpid(); 380*0Sstevel@tonic-gate #endif 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate else 383*0Sstevel@tonic-gate ret=id_callback(); 384*0Sstevel@tonic-gate return(ret); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate void CRYPTO_lock(int mode, int type, const char *file, int line) 388*0Sstevel@tonic-gate { 389*0Sstevel@tonic-gate #ifdef LOCK_DEBUG 390*0Sstevel@tonic-gate { 391*0Sstevel@tonic-gate char *rw_text,*operation_text; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate if (mode & CRYPTO_LOCK) 394*0Sstevel@tonic-gate operation_text="lock "; 395*0Sstevel@tonic-gate else if (mode & CRYPTO_UNLOCK) 396*0Sstevel@tonic-gate operation_text="unlock"; 397*0Sstevel@tonic-gate else 398*0Sstevel@tonic-gate operation_text="ERROR "; 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate if (mode & CRYPTO_READ) 401*0Sstevel@tonic-gate rw_text="r"; 402*0Sstevel@tonic-gate else if (mode & CRYPTO_WRITE) 403*0Sstevel@tonic-gate rw_text="w"; 404*0Sstevel@tonic-gate else 405*0Sstevel@tonic-gate rw_text="ERROR"; 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", 408*0Sstevel@tonic-gate CRYPTO_thread_id(), rw_text, operation_text, 409*0Sstevel@tonic-gate CRYPTO_get_lock_name(type), file, line); 410*0Sstevel@tonic-gate } 411*0Sstevel@tonic-gate #endif 412*0Sstevel@tonic-gate if (type < 0) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate if (dynlock_lock_callback != NULL) 415*0Sstevel@tonic-gate { 416*0Sstevel@tonic-gate struct CRYPTO_dynlock_value *pointer 417*0Sstevel@tonic-gate = CRYPTO_get_dynlock_value(type); 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate OPENSSL_assert(pointer != NULL); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate dynlock_lock_callback(mode, pointer, file, line); 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate CRYPTO_destroy_dynlockid(type); 424*0Sstevel@tonic-gate } 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate else 427*0Sstevel@tonic-gate if (locking_callback != NULL) 428*0Sstevel@tonic-gate locking_callback(mode,type,file,line); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 432*0Sstevel@tonic-gate int line) 433*0Sstevel@tonic-gate { 434*0Sstevel@tonic-gate int ret = 0; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate if (add_lock_callback != NULL) 437*0Sstevel@tonic-gate { 438*0Sstevel@tonic-gate #ifdef LOCK_DEBUG 439*0Sstevel@tonic-gate int before= *pointer; 440*0Sstevel@tonic-gate #endif 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate ret=add_lock_callback(pointer,amount,type,file,line); 443*0Sstevel@tonic-gate #ifdef LOCK_DEBUG 444*0Sstevel@tonic-gate fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 445*0Sstevel@tonic-gate CRYPTO_thread_id(), 446*0Sstevel@tonic-gate before,amount,ret, 447*0Sstevel@tonic-gate CRYPTO_get_lock_name(type), 448*0Sstevel@tonic-gate file,line); 449*0Sstevel@tonic-gate #endif 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate else 452*0Sstevel@tonic-gate { 453*0Sstevel@tonic-gate CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate ret= *pointer+amount; 456*0Sstevel@tonic-gate #ifdef LOCK_DEBUG 457*0Sstevel@tonic-gate fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 458*0Sstevel@tonic-gate CRYPTO_thread_id(), 459*0Sstevel@tonic-gate *pointer,amount,ret, 460*0Sstevel@tonic-gate CRYPTO_get_lock_name(type), 461*0Sstevel@tonic-gate file,line); 462*0Sstevel@tonic-gate #endif 463*0Sstevel@tonic-gate *pointer=ret; 464*0Sstevel@tonic-gate CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate return(ret); 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate const char *CRYPTO_get_lock_name(int type) 470*0Sstevel@tonic-gate { 471*0Sstevel@tonic-gate if (type < 0) 472*0Sstevel@tonic-gate return("dynamic"); 473*0Sstevel@tonic-gate else if (type < CRYPTO_NUM_LOCKS) 474*0Sstevel@tonic-gate return(lock_names[type]); 475*0Sstevel@tonic-gate else if (type-CRYPTO_NUM_LOCKS > sk_num(app_locks)) 476*0Sstevel@tonic-gate return("ERROR"); 477*0Sstevel@tonic-gate else 478*0Sstevel@tonic-gate return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate #ifdef _DLL 482*0Sstevel@tonic-gate #ifdef OPENSSL_SYS_WIN32 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* All we really need to do is remove the 'error' state when a thread 485*0Sstevel@tonic-gate * detaches */ 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, 488*0Sstevel@tonic-gate LPVOID lpvReserved) 489*0Sstevel@tonic-gate { 490*0Sstevel@tonic-gate switch(fdwReason) 491*0Sstevel@tonic-gate { 492*0Sstevel@tonic-gate case DLL_PROCESS_ATTACH: 493*0Sstevel@tonic-gate break; 494*0Sstevel@tonic-gate case DLL_THREAD_ATTACH: 495*0Sstevel@tonic-gate break; 496*0Sstevel@tonic-gate case DLL_THREAD_DETACH: 497*0Sstevel@tonic-gate ERR_remove_state(0); 498*0Sstevel@tonic-gate break; 499*0Sstevel@tonic-gate case DLL_PROCESS_DETACH: 500*0Sstevel@tonic-gate break; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate return(TRUE); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate #endif 505*0Sstevel@tonic-gate 506*0Sstevel@tonic-gate #endif 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate void OpenSSLDie(const char *file,int line,const char *assertion) 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate fprintf(stderr, 511*0Sstevel@tonic-gate "%s(%d): OpenSSL internal error, assertion failed: %s\n", 512*0Sstevel@tonic-gate file,line,assertion); 513*0Sstevel@tonic-gate abort(); 514*0Sstevel@tonic-gate } 515