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