cryptlib.c revision 267654
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@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@cryptsoft.com).  This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
56 * All rights reserved.
57 *
58 * This package is an SSL implementation written
59 * by Eric Young (eay@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@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@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@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)
121static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */
122#endif
123
124static void (MS_FAR *locking_callback)(int mode,int type,
125	const char *file,int line)=NULL;
126static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
127	int type,const char *file,int line)=NULL;
128static unsigned long (MS_FAR *id_callback)(void)=NULL;
129
130int CRYPTO_num_locks(void)
131	{
132	return CRYPTO_NUM_LOCKS;
133	}
134
135void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file,
136		int line)
137	{
138	return(locking_callback);
139	}
140
141int (*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
147void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
148					      const char *file,int line))
149	{
150	locking_callback=func;
151	}
152
153void 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
159unsigned long (*CRYPTO_get_id_callback(void))(void)
160	{
161	return(id_callback);
162	}
163
164void CRYPTO_set_id_callback(unsigned long (*func)(void))
165	{
166	id_callback=func;
167	}
168
169unsigned 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
190static void (*do_dynlock_cb)(int mode, int type, const char *file, int line);
191
192void 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
198void 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
233int 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
275unsigned long  OPENSSL_ia32cap_P=0;
276unsigned 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
280void 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
301unsigned long *OPENSSL_ia32cap_loc(void) { return NULL; }
302#endif
303int OPENSSL_NONPIC_relocated = 0;
304#if !defined(OPENSSL_CPUID_SETUP)
305void 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
314static int DllInit(void) __attribute__((constructor));
315#elif defined(_MSC_VER)
316static 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
327static 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
373BOOL 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		break;
400	case DLL_PROCESS_DETACH:
401		break;
402		}
403	return(TRUE);
404	}
405#endif
406
407#endif
408
409#if defined(_WIN32) && !defined(__CYGWIN__)
410#include <tchar.h>
411
412#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
413int OPENSSL_isservice(void)
414{ HWINSTA h;
415  DWORD len;
416  WCHAR *name;
417
418    (void)GetDesktopWindow(); /* return value is ignored */
419
420    h = GetProcessWindowStation();
421    if (h==NULL) return -1;
422
423    if (GetUserObjectInformationW (h,UOI_NAME,NULL,0,&len) ||
424	GetLastError() != ERROR_INSUFFICIENT_BUFFER)
425	return -1;
426
427    if (len>512) return -1;		/* paranoia */
428    len++,len&=~1;			/* paranoia */
429#ifdef _MSC_VER
430    name=(WCHAR *)_alloca(len+sizeof(WCHAR));
431#else
432    name=(WCHAR *)alloca(len+sizeof(WCHAR));
433#endif
434    if (!GetUserObjectInformationW (h,UOI_NAME,name,len,&len))
435	return -1;
436
437    len++,len&=~1;			/* paranoia */
438    name[len/sizeof(WCHAR)]=L'\0';	/* paranoia */
439#if 1
440    /* This doesn't cover "interactive" services [working with real
441     * WinSta0's] nor programs started non-interactively by Task
442     * Scheduler [those are working with SAWinSta]. */
443    if (wcsstr(name,L"Service-0x"))	return 1;
444#else
445    /* This covers all non-interactive programs such as services. */
446    if (!wcsstr(name,L"WinSta0"))	return 1;
447#endif
448    else				return 0;
449}
450#else
451int OPENSSL_isservice(void) { return 0; }
452#endif
453
454void OPENSSL_showfatal (const char *fmta,...)
455{ va_list ap;
456  TCHAR buf[256];
457  const TCHAR *fmt;
458#ifdef STD_ERROR_HANDLE	/* what a dirty trick! */
459  HANDLE h;
460
461    if ((h=GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
462	GetFileType(h)!=FILE_TYPE_UNKNOWN)
463    {	/* must be console application */
464	va_start (ap,fmta);
465	vfprintf (stderr,fmta,ap);
466	va_end (ap);
467	return;
468    }
469#endif
470
471    if (sizeof(TCHAR)==sizeof(char))
472	fmt=(const TCHAR *)fmta;
473    else do
474    { int    keepgoing;
475      size_t len_0=strlen(fmta)+1,i;
476      WCHAR *fmtw;
477
478#ifdef _MSC_VER
479	fmtw = (WCHAR *)_alloca (len_0*sizeof(WCHAR));
480#else
481	fmtw = (WCHAR *)alloca (len_0*sizeof(WCHAR));
482#endif
483	if (fmtw == NULL) { fmt=(const TCHAR *)L"no stack?"; break; }
484
485#ifndef OPENSSL_NO_MULTIBYTE
486	if (!MultiByteToWideChar(CP_ACP,0,fmta,len_0,fmtw,len_0))
487#endif
488	    for (i=0;i<len_0;i++) fmtw[i]=(WCHAR)fmta[i];
489
490	for (i=0;i<len_0;i++)
491	{   if (fmtw[i]==L'%') do
492	    {	keepgoing=0;
493		switch (fmtw[i+1])
494		{   case L'0': case L'1': case L'2': case L'3': case L'4':
495		    case L'5': case L'6': case L'7': case L'8': case L'9':
496		    case L'.': case L'*':
497		    case L'-':	i++; keepgoing=1; break;
498		    case L's':	fmtw[i+1]=L'S';   break;
499		    case L'S':	fmtw[i+1]=L's';   break;
500		    case L'c':	fmtw[i+1]=L'C';   break;
501		    case L'C':	fmtw[i+1]=L'c';   break;
502		}
503	    } while (keepgoing);
504	}
505	fmt = (const TCHAR *)fmtw;
506    } while (0);
507
508    va_start (ap,fmta);
509    _vsntprintf (buf,sizeof(buf)/sizeof(TCHAR)-1,fmt,ap);
510    buf [sizeof(buf)/sizeof(TCHAR)-1] = _T('\0');
511    va_end (ap);
512
513#if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
514    /* this -------------v--- guards NT-specific calls */
515    if (GetVersion() < 0x80000000 && OPENSSL_isservice() > 0)
516    {	HANDLE h = RegisterEventSource(0,_T("OPENSSL"));
517	const TCHAR *pmsg=buf;
518	ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0);
519	DeregisterEventSource(h);
520    }
521    else
522#endif
523	MessageBox (NULL,buf,_T("OpenSSL: FATAL"),MB_OK|MB_ICONSTOP);
524}
525#else
526void OPENSSL_showfatal (const char *fmta,...)
527{ va_list ap;
528
529    va_start (ap,fmta);
530    vfprintf (stderr,fmta,ap);
531    va_end (ap);
532}
533int OPENSSL_isservice (void) { return 0; }
534#endif
535
536void OpenSSLDie(const char *file,int line,const char *assertion)
537	{
538	OPENSSL_showfatal(
539		"%s(%d): OpenSSL internal error, assertion failed: %s\n",
540		file,line,assertion);
541	abort();
542	}
543
544void *OPENSSL_stderr(void)	{ return stderr; }
545
546#ifndef OPENSSL_FIPS
547
548int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
549	{
550	size_t i;
551	const unsigned char *a = in_a;
552	const unsigned char *b = in_b;
553	unsigned char x = 0;
554
555	for (i = 0; i < len; i++)
556		x |= a[i] ^ b[i];
557
558	return x;
559	}
560#endif
561