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