1/* 2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19/* crypto/cryptlib.c */ 20/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 21 * All rights reserved. 22 * 23 * This package is an SSL implementation written 24 * by Eric Young (eay@cryptsoft.com). 25 * The implementation was written so as to conform with Netscapes SSL. 26 * 27 * This library is free for commercial and non-commercial use as long as 28 * the following conditions are aheared to. The following conditions 29 * apply to all code found in this distribution, be it the RC4, RSA, 30 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 31 * included with this distribution is covered by the same copyright terms 32 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 33 * 34 * Copyright remains Eric Young's, and as such any Copyright notices in 35 * the code are not to be removed. 36 * If this package is used in a product, Eric Young should be given attribution 37 * as the author of the parts of the library used. 38 * This can be in the form of a textual message at program startup or 39 * in documentation (online or textual) provided with the package. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. All advertising materials mentioning features or use of this software 50 * must display the following acknowledgement: 51 * "This product includes cryptographic software written by 52 * Eric Young (eay@cryptsoft.com)" 53 * The word 'cryptographic' can be left out if the rouines from the library 54 * being used are not cryptographic related :-). 55 * 4. If you include any Windows specific code (or a derivative thereof) from 56 * the apps directory (application code) you must include an acknowledgement: 57 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 58 * 59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * The licence and distribution terms for any publically available version or 72 * derivative of this code cannot be changed. i.e. this code cannot simply be 73 * copied and put under another distribution licence 74 * [including the GNU Public Licence.] 75 */ 76 77#include <stdio.h> 78#include <string.h> 79#include "cryptlib.h" 80#include <openssl/crypto.h> 81 82#if defined(WIN32) || defined(WIN16) 83static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ 84#endif 85 86/* real #defines in crypto.h, keep these upto date */ 87#if defined(LOCK_DEBUG) 88static const char* const lock_names[CRYPTO_NUM_LOCKS] = 89 { 90 "<<ERROR>>", 91 "err", 92 "err_hash", 93 "x509", 94 "x509_info", 95 "x509_pkey", 96 "x509_crl", 97 "x509_req", 98 "dsa", 99 "rsa", 100 "evp_pkey", 101 "x509_store", 102 "ssl_ctx", 103 "ssl_cert", 104 "ssl_session", 105 "ssl_sess_cert", 106 "ssl", 107 "rand", 108 "debug_malloc", 109 "BIO", 110 "gethostbyname", 111 "getservbyname", 112 "readdir", 113 "RSA_blinding", 114 "dh", 115 "debug_malloc2", 116#if CRYPTO_NUM_LOCKS != 26 117# error "Inconsistency between crypto.h and cryptlib.c" 118#endif 119 }; 120#endif /*LOCK_DEBUG*/ 121 122static STACK *app_locks=NULL; 123 124#if CRYPTO_CALLBACK_ENABLE 125static void (MS_FAR *locking_callback)(int mode,int type, 126 const char *file,int line)=NULL; 127static int (MS_FAR *add_lock_callback)(int *pointer,int amount, 128 int type,const char *file,int line)=NULL; 129static unsigned long (MS_FAR *id_callback)(void)=NULL; 130#endif /* CRYPTO_CALLBACK_ENABLE */ 131 132int CRYPTO_get_new_lockid(char *name) 133 { 134 char *str; 135 int i; 136 137 /* A hack to make Visual C++ 5.0 work correctly when linking as 138 * a DLL using /MT. Without this, the application cannot use 139 * and floating point printf's. 140 * It also seems to be needed for Visual C 1.5 (win16) */ 141#if defined(WIN32) || defined(WIN16) 142 SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; 143#endif 144 145 if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL)) 146 { 147 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 148 return(0); 149 } 150 if ((str=BUF_strdup(name)) == NULL) 151 return(0); 152 i=sk_push(app_locks,str); 153 if (!i) 154 Free(str); 155 else 156 i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ 157 return(i); 158 } 159 160int CRYPTO_num_locks(void) 161 { 162 return CRYPTO_NUM_LOCKS; 163 } 164 165void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, 166 int line) 167 { 168 #if CRYPTO_CALLBACK_ENABLE 169 return(locking_callback); 170 #else 171 return NULL; 172 #endif 173 } 174 175int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, 176 const char *file,int line) 177 { 178 #if CRYPTO_CALLBACK_ENABLE 179 return(add_lock_callback); 180 #else 181 return NULL; 182 #endif 183 } 184 185void CRYPTO_set_locking_callback(void (*func)(int mode,int type, 186 const char *file,int line)) 187 { 188 #if CRYPTO_CALLBACK_ENABLE 189 locking_callback=func; 190 #endif 191 } 192 193void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, 194 const char *file,int line)) 195 { 196 #if CRYPTO_CALLBACK_ENABLE 197 add_lock_callback=func; 198 #endif 199 } 200 201unsigned long (*CRYPTO_get_id_callback(void))(void) 202 { 203 #if CRYPTO_CALLBACK_ENABLE 204 return(id_callback); 205 #else 206 return NULL; 207 #endif 208 } 209 210void CRYPTO_set_id_callback(unsigned long (*func)(void)) 211 { 212 #if CRYPTO_CALLBACK_ENABLE 213 id_callback=func; 214 #endif 215 } 216 217unsigned long CRYPTO_thread_id(void) 218 { 219 unsigned long ret=0; 220 221#if CRYPTO_CALLBACK_ENABLE 222 if (id_callback == NULL) 223 { 224#ifdef WIN16 225 ret=(unsigned long)GetCurrentTask(); 226#elif defined(WIN32) 227 ret=(unsigned long)GetCurrentThreadId(); 228#elif defined(GETPID_IS_MEANINGLESS) 229 ret=1L; 230#else 231 ret=(unsigned long)getpid(); 232#endif 233 } 234 else 235 ret=id_callback(); 236#endif /* CRYPTO_CALLBACK_ENABLE */ 237 return(ret); 238 } 239 240void CRYPTO_lock(int mode, int type, const char *file, int line) 241 { 242#ifdef LOCK_DEBUG 243 { 244 char *rw_text,*operation_text; 245 246 if (mode & CRYPTO_LOCK) 247 operation_text="lock "; 248 else if (mode & CRYPTO_UNLOCK) 249 operation_text="unlock"; 250 else 251 operation_text="ERROR "; 252 253 if (mode & CRYPTO_READ) 254 rw_text="r"; 255 else if (mode & CRYPTO_WRITE) 256 rw_text="w"; 257 else 258 rw_text="ERROR"; 259 260 fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", 261 CRYPTO_thread_id(), rw_text, operation_text, 262 CRYPTO_get_lock_name(type), file, line); 263 } 264#endif 265#if CRYPTO_CALLBACK_ENABLE 266 if (locking_callback != NULL) 267 locking_callback(mode,type,file,line); 268#endif 269 } 270 271int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 272 int line) 273 { 274 int ret; 275#if CRYPTO_CALLBACK_ENABLE 276 if (add_lock_callback != NULL) 277 { 278#ifdef LOCK_DEBUG 279 int before= *pointer; 280#endif 281 282 ret=add_lock_callback(pointer,amount,type,file,line); 283#ifdef LOCK_DEBUG 284 fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 285 CRYPTO_thread_id(), 286 before,amount,ret, 287 CRYPTO_get_lock_name(type), 288 file,line); 289#endif 290 *pointer=ret; 291 } 292 else 293#endif /* CRYPTO_CALLBACK_ENABLE */ 294 { 295 CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); 296 297 ret= *pointer+amount; 298#ifdef LOCK_DEBUG 299 fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 300 CRYPTO_thread_id(), 301 *pointer,amount,ret, 302 CRYPTO_get_lock_name(type), 303 file,line); 304#endif 305 *pointer=ret; 306 CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); 307 } 308 return(ret); 309 } 310 311#ifdef LOCK_DEBUG 312const char *CRYPTO_get_lock_name(int type) 313 { 314 if (type < 0) 315 return("ERROR"); 316 else if (type < CRYPTO_NUM_LOCKS) 317 return(lock_names[type]); 318 else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks)) 319 return("ERROR"); 320 else 321 return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); 322 } 323#endif /*LOCK_DEBUG*/ 324 325#ifdef _DLL 326#ifdef WIN32 327 328/* All we really need to do is remove the 'error' state when a thread 329 * detaches */ 330 331BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, 332 LPVOID lpvReserved) 333 { 334 switch(fdwReason) 335 { 336 case DLL_PROCESS_ATTACH: 337 break; 338 case DLL_THREAD_ATTACH: 339 break; 340 case DLL_THREAD_DETACH: 341 ERR_remove_state(0); 342 break; 343 case DLL_PROCESS_DETACH: 344 break; 345 } 346 return(TRUE); 347 } 348#endif 349 350#endif 351