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
10280304Sjkim *    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.
61280304Sjkim *
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).
68280304Sjkim *
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.
75280304Sjkim *
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 :-).
90280304Sjkim * 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)"
93280304Sjkim *
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.
105280304Sjkim *
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.
113280304Sjkim * 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)
121280304Sjkimstatic 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 */
127280304Sjkimstatic const char *const lock_names[CRYPTO_NUM_LOCKS] = {
128280304Sjkim    "<<ERROR>>",
129280304Sjkim    "err",
130280304Sjkim    "ex_data",
131280304Sjkim    "x509",
132280304Sjkim    "x509_info",
133280304Sjkim    "x509_pkey",
134280304Sjkim    "x509_crl",
135280304Sjkim    "x509_req",
136280304Sjkim    "dsa",
137280304Sjkim    "rsa",
138280304Sjkim    "evp_pkey",
139280304Sjkim    "x509_store",
140280304Sjkim    "ssl_ctx",
141280304Sjkim    "ssl_cert",
142280304Sjkim    "ssl_session",
143280304Sjkim    "ssl_sess_cert",
144280304Sjkim    "ssl",
145280304Sjkim    "ssl_method",
146280304Sjkim    "rand",
147280304Sjkim    "rand2",
148280304Sjkim    "debug_malloc",
149280304Sjkim    "BIO",
150280304Sjkim    "gethostbyname",
151280304Sjkim    "getservbyname",
152280304Sjkim    "readdir",
153280304Sjkim    "RSA_blinding",
154280304Sjkim    "dh",
155280304Sjkim    "debug_malloc2",
156280304Sjkim    "dso",
157280304Sjkim    "dynlock",
158280304Sjkim    "engine",
159280304Sjkim    "ui",
160280304Sjkim    "ecdsa",
161280304Sjkim    "ec",
162280304Sjkim    "ecdh",
163280304Sjkim    "bn",
164280304Sjkim    "ec_pre_comp",
165280304Sjkim    "store",
166280304Sjkim    "comp",
167280304Sjkim    "fips",
168280304Sjkim    "fips2",
169238405Sjkim#if CRYPTO_NUM_LOCKS != 41
170238405Sjkim# error "Inconsistency between crypto.h and cryptlib.c"
171238405Sjkim#endif
172280304Sjkim};
173238405Sjkim
174280304Sjkim/*
175280304Sjkim * This is for applications to allocate new type names in the non-dynamic
176280304Sjkim * array of lock names.  These are numbered with positive numbers.
177280304Sjkim */
178280304Sjkimstatic STACK_OF(OPENSSL_STRING) *app_locks = NULL;
179238405Sjkim
180280304Sjkim/*
181280304Sjkim * For applications that want a more dynamic way of handling threads, the
182280304Sjkim * following stack is used.  These are externally numbered with negative
183280304Sjkim * numbers.
184280304Sjkim */
185280304Sjkimstatic STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
186238405Sjkim
187280304Sjkimstatic void (MS_FAR *locking_callback) (int mode, int type,
188280304Sjkim                                        const char *file, int line) = 0;
189280304Sjkimstatic int (MS_FAR *add_lock_callback) (int *pointer, int amount,
190280304Sjkim                                        int type, const char *file,
191280304Sjkim                                        int line) = 0;
192238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
193280304Sjkimstatic unsigned long (MS_FAR *id_callback) (void) = 0;
194238405Sjkim#endif
195280304Sjkimstatic void (MS_FAR *threadid_callback) (CRYPTO_THREADID *) = 0;
196238405Sjkimstatic struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
197280304Sjkim (const char *file, int line) = 0;
198280304Sjkimstatic void (MS_FAR *dynlock_lock_callback) (int mode,
199280304Sjkim                                             struct CRYPTO_dynlock_value *l,
200280304Sjkim                                             const char *file, int line) = 0;
201280304Sjkimstatic void (MS_FAR *dynlock_destroy_callback) (struct CRYPTO_dynlock_value
202280304Sjkim                                                *l, const char *file,
203280304Sjkim                                                int line) = 0;
20468651Skris
205238405Sjkimint CRYPTO_get_new_lockid(char *name)
206280304Sjkim{
207280304Sjkim    char *str;
208280304Sjkim    int i;
209238405Sjkim
210238405Sjkim#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
211280304Sjkim    /*
212280304Sjkim     * A hack to make Visual C++ 5.0 work correctly when linking as a DLL
213280304Sjkim     * using /MT. Without this, the application cannot use any floating point
214280304Sjkim     * printf's. It also seems to be needed for Visual C 1.5 (win16)
215280304Sjkim     */
216280304Sjkim    SSLeay_MSVC5_hack = (double)name[0] * (double)name[1];
217238405Sjkim#endif
218238405Sjkim
219280304Sjkim    if ((app_locks == NULL)
220280304Sjkim        && ((app_locks = sk_OPENSSL_STRING_new_null()) == NULL)) {
221280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
222280304Sjkim        return (0);
223280304Sjkim    }
224280304Sjkim    if ((str = BUF_strdup(name)) == NULL) {
225280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
226280304Sjkim        return (0);
227280304Sjkim    }
228280304Sjkim    i = sk_OPENSSL_STRING_push(app_locks, str);
229280304Sjkim    if (!i)
230280304Sjkim        OPENSSL_free(str);
231280304Sjkim    else
232280304Sjkim        i += CRYPTO_NUM_LOCKS;  /* gap of one :-) */
233280304Sjkim    return (i);
234280304Sjkim}
235238405Sjkim
23655714Skrisint CRYPTO_num_locks(void)
237280304Sjkim{
238280304Sjkim    return CRYPTO_NUM_LOCKS;
239280304Sjkim}
24055714Skris
241238405Sjkimint CRYPTO_get_new_dynlockid(void)
242280304Sjkim{
243280304Sjkim    int i = 0;
244280304Sjkim    CRYPTO_dynlock *pointer = NULL;
245238405Sjkim
246280304Sjkim    if (dynlock_create_callback == NULL) {
247280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
248280304Sjkim                  CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
249280304Sjkim        return (0);
250280304Sjkim    }
251280304Sjkim    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
252280304Sjkim    if ((dyn_locks == NULL)
253280304Sjkim        && ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) {
254280304Sjkim        CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
255280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
256280304Sjkim        return (0);
257280304Sjkim    }
258280304Sjkim    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
259238405Sjkim
260280304Sjkim    pointer = (CRYPTO_dynlock *) OPENSSL_malloc(sizeof(CRYPTO_dynlock));
261280304Sjkim    if (pointer == NULL) {
262280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
263280304Sjkim        return (0);
264280304Sjkim    }
265280304Sjkim    pointer->references = 1;
266280304Sjkim    pointer->data = dynlock_create_callback(__FILE__, __LINE__);
267280304Sjkim    if (pointer->data == NULL) {
268280304Sjkim        OPENSSL_free(pointer);
269280304Sjkim        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
270280304Sjkim        return (0);
271280304Sjkim    }
272238405Sjkim
273280304Sjkim    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
274280304Sjkim    /* First, try to find an existing empty slot */
275280304Sjkim    i = sk_CRYPTO_dynlock_find(dyn_locks, NULL);
276280304Sjkim    /* If there was none, push, thereby creating a new one */
277280304Sjkim    if (i == -1)
278280304Sjkim        /*
279280304Sjkim         * Since sk_push() returns the number of items on the stack, not the
280280304Sjkim         * location of the pushed item, we need to transform the returned
281280304Sjkim         * number into a position, by decreasing it.
282280304Sjkim         */
283280304Sjkim        i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1;
284280304Sjkim    else
285280304Sjkim        /*
286280304Sjkim         * If we found a place with a NULL pointer, put our pointer in it.
287280304Sjkim         */
288280304Sjkim        (void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer);
289280304Sjkim    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
290238405Sjkim
291280304Sjkim    if (i == -1) {
292280304Sjkim        dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
293280304Sjkim        OPENSSL_free(pointer);
294280304Sjkim    } else
295280304Sjkim        i += 1;                 /* to avoid 0 */
296280304Sjkim    return -i;
297280304Sjkim}
298238405Sjkim
299238405Sjkimvoid CRYPTO_destroy_dynlockid(int i)
300280304Sjkim{
301280304Sjkim    CRYPTO_dynlock *pointer = NULL;
302280304Sjkim    if (i)
303280304Sjkim        i = -i - 1;
304280304Sjkim    if (dynlock_destroy_callback == NULL)
305280304Sjkim        return;
306238405Sjkim
307280304Sjkim    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
308238405Sjkim
309280304Sjkim    if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) {
310280304Sjkim        CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
311280304Sjkim        return;
312280304Sjkim    }
313280304Sjkim    pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
314280304Sjkim    if (pointer != NULL) {
315280304Sjkim        --pointer->references;
316238405Sjkim#ifdef REF_CHECK
317280304Sjkim        if (pointer->references < 0) {
318280304Sjkim            fprintf(stderr,
319280304Sjkim                    "CRYPTO_destroy_dynlockid, bad reference count\n");
320280304Sjkim            abort();
321280304Sjkim        } else
322238405Sjkim#endif
323280304Sjkim        if (pointer->references <= 0) {
324280304Sjkim            (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
325280304Sjkim        } else
326280304Sjkim            pointer = NULL;
327280304Sjkim    }
328280304Sjkim    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
329238405Sjkim
330280304Sjkim    if (pointer) {
331280304Sjkim        dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
332280304Sjkim        OPENSSL_free(pointer);
333280304Sjkim    }
334280304Sjkim}
335238405Sjkim
336238405Sjkimstruct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
337280304Sjkim{
338280304Sjkim    CRYPTO_dynlock *pointer = NULL;
339280304Sjkim    if (i)
340280304Sjkim        i = -i - 1;
341238405Sjkim
342280304Sjkim    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
343238405Sjkim
344280304Sjkim    if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
345280304Sjkim        pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
346280304Sjkim    if (pointer)
347280304Sjkim        pointer->references++;
348238405Sjkim
349280304Sjkim    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
350238405Sjkim
351280304Sjkim    if (pointer)
352280304Sjkim        return pointer->data;
353280304Sjkim    return NULL;
354280304Sjkim}
355238405Sjkim
356238405Sjkimstruct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
357280304Sjkim (const char *file, int line) {
358280304Sjkim    return (dynlock_create_callback);
359280304Sjkim}
360238405Sjkim
361280304Sjkimvoid (*CRYPTO_get_dynlock_lock_callback(void)) (int mode,
362280304Sjkim                                                struct CRYPTO_dynlock_value
363280304Sjkim                                                *l, const char *file,
364280304Sjkim                                                int line) {
365280304Sjkim    return (dynlock_lock_callback);
366280304Sjkim}
367238405Sjkim
368238405Sjkimvoid (*CRYPTO_get_dynlock_destroy_callback(void))
369280304Sjkim (struct CRYPTO_dynlock_value *l, const char *file, int line) {
370280304Sjkim    return (dynlock_destroy_callback);
371280304Sjkim}
372238405Sjkim
373238405Sjkimvoid CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
374280304Sjkim                                         (const char *file, int line))
375280304Sjkim{
376280304Sjkim    dynlock_create_callback = func;
377280304Sjkim}
378238405Sjkim
379280304Sjkimvoid CRYPTO_set_dynlock_lock_callback(void (*func) (int mode,
380280304Sjkim                                                    struct
381280304Sjkim                                                    CRYPTO_dynlock_value *l,
382280304Sjkim                                                    const char *file,
383280304Sjkim                                                    int line))
384280304Sjkim{
385280304Sjkim    dynlock_lock_callback = func;
386280304Sjkim}
387238405Sjkim
388238405Sjkimvoid CRYPTO_set_dynlock_destroy_callback(void (*func)
389280304Sjkim                                          (struct CRYPTO_dynlock_value *l,
390280304Sjkim                                           const char *file, int line))
391280304Sjkim{
392280304Sjkim    dynlock_destroy_callback = func;
393280304Sjkim}
394238405Sjkim
395280304Sjkimvoid (*CRYPTO_get_locking_callback(void)) (int mode, int type,
396280304Sjkim                                           const char *file, int line) {
397280304Sjkim    return (locking_callback);
398280304Sjkim}
399238405Sjkim
400280304Sjkimint (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
401280304Sjkim                                           const char *file, int line) {
402280304Sjkim    return (add_lock_callback);
403280304Sjkim}
40455714Skris
405280304Sjkimvoid CRYPTO_set_locking_callback(void (*func) (int mode, int type,
406280304Sjkim                                               const char *file, int line))
407280304Sjkim{
408280304Sjkim    /*
409280304Sjkim     * Calling this here ensures initialisation before any threads are
410280304Sjkim     * started.
411280304Sjkim     */
412280304Sjkim    OPENSSL_init();
413280304Sjkim    locking_callback = func;
414280304Sjkim}
41555714Skris
416280304Sjkimvoid CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
417280304Sjkim                                               const char *file, int line))
418280304Sjkim{
419280304Sjkim    add_lock_callback = func;
420280304Sjkim}
42155714Skris
422280304Sjkim/*
423280304Sjkim * the memset() here and in set_pointer() seem overkill, but for the sake of
424280304Sjkim * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause
425280304Sjkim * two "equal" THREADID structs to not be memcmp()-identical.
426280304Sjkim */
427238405Sjkimvoid CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
428280304Sjkim{
429280304Sjkim    memset(id, 0, sizeof(*id));
430280304Sjkim    id->val = val;
431280304Sjkim}
432238405Sjkim
433238405Sjkimstatic const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
434280304Sjkim
435238405Sjkimvoid CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
436280304Sjkim{
437280304Sjkim    unsigned char *dest = (void *)&id->val;
438280304Sjkim    unsigned int accum = 0;
439280304Sjkim    unsigned char dnum = sizeof(id->val);
440238405Sjkim
441280304Sjkim    memset(id, 0, sizeof(*id));
442280304Sjkim    id->ptr = ptr;
443280304Sjkim    if (sizeof(id->val) >= sizeof(id->ptr)) {
444280304Sjkim        /*
445280304Sjkim         * 'ptr' can be embedded in 'val' without loss of uniqueness
446280304Sjkim         */
447280304Sjkim        id->val = (unsigned long)id->ptr;
448280304Sjkim        return;
449280304Sjkim    }
450280304Sjkim    /*
451280304Sjkim     * hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a
452280304Sjkim     * linear function over the bytes in 'ptr', the co-efficients of which
453280304Sjkim     * are a sequence of low-primes (hash_coeffs is an 8-element cycle) - the
454280304Sjkim     * starting prime for the sequence varies for each byte of 'val' (unique
455280304Sjkim     * polynomials unless pointers are >64-bit). For added spice, the totals
456280304Sjkim     * accumulate rather than restarting from zero, and the index of the
457280304Sjkim     * 'val' byte is added each time (position dependence). If I was a
458280304Sjkim     * black-belt, I'd scan big-endian pointers in reverse to give low-order
459280304Sjkim     * bits more play, but this isn't crypto and I'd prefer nobody mistake it
460280304Sjkim     * as such. Plus I'm lazy.
461280304Sjkim     */
462280304Sjkim    while (dnum--) {
463280304Sjkim        const unsigned char *src = (void *)&id->ptr;
464280304Sjkim        unsigned char snum = sizeof(id->ptr);
465280304Sjkim        while (snum--)
466280304Sjkim            accum += *(src++) * hash_coeffs[(snum + dnum) & 7];
467280304Sjkim        accum += dnum;
468280304Sjkim        *(dest++) = accum & 255;
469280304Sjkim    }
470280304Sjkim}
471238405Sjkim
472280304Sjkimint CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *))
473280304Sjkim{
474280304Sjkim    if (threadid_callback)
475280304Sjkim        return 0;
476280304Sjkim    threadid_callback = func;
477280304Sjkim    return 1;
478280304Sjkim}
479238405Sjkim
480280304Sjkimvoid (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *) {
481280304Sjkim    return threadid_callback;
482280304Sjkim}
483238405Sjkim
484238405Sjkimvoid CRYPTO_THREADID_current(CRYPTO_THREADID *id)
485280304Sjkim{
486280304Sjkim    if (threadid_callback) {
487280304Sjkim        threadid_callback(id);
488280304Sjkim        return;
489280304Sjkim    }
490238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
491280304Sjkim    /* If the deprecated callback was set, fall back to that */
492280304Sjkim    if (id_callback) {
493280304Sjkim        CRYPTO_THREADID_set_numeric(id, id_callback());
494280304Sjkim        return;
495280304Sjkim    }
496238405Sjkim#endif
497280304Sjkim    /* Else pick a backup */
498238405Sjkim#ifdef OPENSSL_SYS_WIN16
499280304Sjkim    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask());
500238405Sjkim#elif defined(OPENSSL_SYS_WIN32)
501280304Sjkim    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
502238405Sjkim#elif defined(OPENSSL_SYS_BEOS)
503280304Sjkim    CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
504238405Sjkim#else
505280304Sjkim    /* For everything else, default to using the address of 'errno' */
506280304Sjkim    CRYPTO_THREADID_set_pointer(id, (void *)&errno);
507238405Sjkim#endif
508280304Sjkim}
509238405Sjkim
510238405Sjkimint CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
511280304Sjkim{
512280304Sjkim    return memcmp(a, b, sizeof(*a));
513280304Sjkim}
514238405Sjkim
515238405Sjkimvoid CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
516280304Sjkim{
517280304Sjkim    memcpy(dest, src, sizeof(*src));
518280304Sjkim}
519238405Sjkim
520238405Sjkimunsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
521280304Sjkim{
522280304Sjkim    return id->val;
523280304Sjkim}
524238405Sjkim
525238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
526280304Sjkimunsigned long (*CRYPTO_get_id_callback(void)) (void) {
527280304Sjkim    return (id_callback);
528280304Sjkim}
52955714Skris
530280304Sjkimvoid CRYPTO_set_id_callback(unsigned long (*func) (void))
531280304Sjkim{
532280304Sjkim    id_callback = func;
533280304Sjkim}
53455714Skris
53555714Skrisunsigned long CRYPTO_thread_id(void)
536280304Sjkim{
537280304Sjkim    unsigned long ret = 0;
53855714Skris
539280304Sjkim    if (id_callback == NULL) {
540280304Sjkim# ifdef OPENSSL_SYS_WIN16
541280304Sjkim        ret = (unsigned long)GetCurrentTask();
542280304Sjkim# elif defined(OPENSSL_SYS_WIN32)
543280304Sjkim        ret = (unsigned long)GetCurrentThreadId();
544280304Sjkim# elif defined(GETPID_IS_MEANINGLESS)
545280304Sjkim        ret = 1L;
546280304Sjkim# elif defined(OPENSSL_SYS_BEOS)
547280304Sjkim        ret = (unsigned long)find_thread(NULL);
548280304Sjkim# else
549280304Sjkim        ret = (unsigned long)getpid();
550280304Sjkim# endif
551280304Sjkim    } else
552280304Sjkim        ret = id_callback();
553280304Sjkim    return (ret);
554280304Sjkim}
55555714Skris#endif
55655714Skris
55755714Skrisvoid CRYPTO_lock(int mode, int type, const char *file, int line)
558280304Sjkim{
55955714Skris#ifdef LOCK_DEBUG
560280304Sjkim    {
561280304Sjkim        CRYPTO_THREADID id;
562280304Sjkim        char *rw_text, *operation_text;
56355714Skris
564280304Sjkim        if (mode & CRYPTO_LOCK)
565280304Sjkim            operation_text = "lock  ";
566280304Sjkim        else if (mode & CRYPTO_UNLOCK)
567280304Sjkim            operation_text = "unlock";
568280304Sjkim        else
569280304Sjkim            operation_text = "ERROR ";
57055714Skris
571280304Sjkim        if (mode & CRYPTO_READ)
572280304Sjkim            rw_text = "r";
573280304Sjkim        else if (mode & CRYPTO_WRITE)
574280304Sjkim            rw_text = "w";
575280304Sjkim        else
576280304Sjkim            rw_text = "ERROR";
57755714Skris
578280304Sjkim        CRYPTO_THREADID_current(&id);
579280304Sjkim        fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
580280304Sjkim                CRYPTO_THREADID_hash(&id), rw_text, operation_text,
581280304Sjkim                CRYPTO_get_lock_name(type), file, line);
582280304Sjkim    }
58355714Skris#endif
584280304Sjkim    if (type < 0) {
585280304Sjkim        if (dynlock_lock_callback != NULL) {
586280304Sjkim            struct CRYPTO_dynlock_value *pointer
587280304Sjkim                = CRYPTO_get_dynlock_value(type);
588238405Sjkim
589280304Sjkim            OPENSSL_assert(pointer != NULL);
590238405Sjkim
591280304Sjkim            dynlock_lock_callback(mode, pointer, file, line);
592238405Sjkim
593280304Sjkim            CRYPTO_destroy_dynlockid(type);
594280304Sjkim        }
595280304Sjkim    } else if (locking_callback != NULL)
596280304Sjkim        locking_callback(mode, type, file, line);
597280304Sjkim}
59855714Skris
59955714Skrisint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
600280304Sjkim                    int line)
601280304Sjkim{
602280304Sjkim    int ret = 0;
60355714Skris
604280304Sjkim    if (add_lock_callback != NULL) {
60555714Skris#ifdef LOCK_DEBUG
606280304Sjkim        int before = *pointer;
60755714Skris#endif
60855714Skris
609280304Sjkim        ret = add_lock_callback(pointer, amount, type, file, line);
61055714Skris#ifdef LOCK_DEBUG
611280304Sjkim        {
612280304Sjkim            CRYPTO_THREADID id;
613280304Sjkim            CRYPTO_THREADID_current(&id);
614280304Sjkim            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
615280304Sjkim                    CRYPTO_THREADID_hash(&id), before, amount, ret,
616280304Sjkim                    CRYPTO_get_lock_name(type), file, line);
617280304Sjkim        }
61855714Skris#endif
619280304Sjkim    } else {
620280304Sjkim        CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
62155714Skris
622280304Sjkim        ret = *pointer + amount;
62355714Skris#ifdef LOCK_DEBUG
624280304Sjkim        {
625280304Sjkim            CRYPTO_THREADID id;
626280304Sjkim            CRYPTO_THREADID_current(&id);
627280304Sjkim            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
628280304Sjkim                    CRYPTO_THREADID_hash(&id),
629280304Sjkim                    *pointer, amount, ret,
630280304Sjkim                    CRYPTO_get_lock_name(type), file, line);
631280304Sjkim        }
63255714Skris#endif
633280304Sjkim        *pointer = ret;
634280304Sjkim        CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
635280304Sjkim    }
636280304Sjkim    return (ret);
637280304Sjkim}
63855714Skris
639238405Sjkimconst char *CRYPTO_get_lock_name(int type)
640280304Sjkim{
641280304Sjkim    if (type < 0)
642280304Sjkim        return ("dynamic");
643280304Sjkim    else if (type < CRYPTO_NUM_LOCKS)
644280304Sjkim        return (lock_names[type]);
645280304Sjkim    else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
646280304Sjkim        return ("ERROR");
647280304Sjkim    else
648280304Sjkim        return (sk_OPENSSL_STRING_value(app_locks, type - CRYPTO_NUM_LOCKS));
649280304Sjkim}
650238405Sjkim
651280304Sjkim#if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
652280304Sjkim        defined(__INTEL__) || \
653280304Sjkim        defined(__x86_64) || defined(__x86_64__) || \
654280304Sjkim        defined(_M_AMD64) || defined(_M_X64)
65555714Skris
656280304Sjkimunsigned int OPENSSL_ia32cap_P[2];
657238405Sjkimunsigned long *OPENSSL_ia32cap_loc(void)
658280304Sjkim{
659280304Sjkim    if (sizeof(long) == 4)
660280304Sjkim        /*
661280304Sjkim         * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
662280304Sjkim         * clear second element to maintain the illusion that vector
663280304Sjkim         * is 32-bit.
664280304Sjkim         */
665280304Sjkim        OPENSSL_ia32cap_P[1] = 0;
666238405Sjkim    return (unsigned long *)OPENSSL_ia32cap_P;
667238405Sjkim}
668160814Ssimon
669280304Sjkim# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
670280304Sjkim#  define OPENSSL_CPUID_SETUP
671280304Sjkim#  if defined(_WIN32)
672238405Sjkimtypedef unsigned __int64 IA32CAP;
673280304Sjkim#  else
674238405Sjkimtypedef unsigned long long IA32CAP;
675280304Sjkim#  endif
676160814Ssimonvoid OPENSSL_cpuid_setup(void)
677280304Sjkim{
678280304Sjkim    static int trigger = 0;
679280304Sjkim    IA32CAP OPENSSL_ia32_cpuid(void);
680280304Sjkim    IA32CAP vec;
681280304Sjkim    char *env;
682160814Ssimon
683280304Sjkim    if (trigger)
684280304Sjkim        return;
685160814Ssimon
686280304Sjkim    trigger = 1;
687280304Sjkim    if ((env = getenv("OPENSSL_ia32cap"))) {
688280304Sjkim        int off = (env[0] == '~') ? 1 : 0;
689280304Sjkim#  if defined(_WIN32)
690280304Sjkim        if (!sscanf(env + off, "%I64i", &vec))
691280304Sjkim            vec = strtoul(env + off, NULL, 0);
692280304Sjkim#  else
693280304Sjkim        if (!sscanf(env + off, "%lli", (long long *)&vec))
694280304Sjkim            vec = strtoul(env + off, NULL, 0);
695280304Sjkim#  endif
696280304Sjkim        if (off)
697280304Sjkim            vec = OPENSSL_ia32_cpuid() & ~vec;
698280304Sjkim    } else
699280304Sjkim        vec = OPENSSL_ia32_cpuid();
700246772Sjkim
701160814Ssimon    /*
702160814Ssimon     * |(1<<10) sets a reserved bit to signal that variable
703160814Ssimon     * was initialized already... This is to avoid interference
704160814Ssimon     * with cpuid snippets in ELF .init segment.
705160814Ssimon     */
706280304Sjkim    OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
707280304Sjkim    OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
708160814Ssimon}
709280304Sjkim# endif
710160814Ssimon
711160814Ssimon#else
712280304Sjkimunsigned long *OPENSSL_ia32cap_loc(void)
713280304Sjkim{
714280304Sjkim    return NULL;
715280304Sjkim}
716160814Ssimon#endif
717160814Ssimonint OPENSSL_NONPIC_relocated = 0;
718238405Sjkim#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
719280304Sjkimvoid OPENSSL_cpuid_setup(void)
720280304Sjkim{
721280304Sjkim}
722160814Ssimon#endif
723160814Ssimon
724160814Ssimon#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
725280304Sjkim# ifdef __CYGWIN__
726160814Ssimon/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
727280304Sjkim#  include <windows.h>
728280304Sjkim/*
729280304Sjkim * this has side-effect of _WIN32 getting defined, which otherwise is
730280304Sjkim * mutually exclusive with __CYGWIN__...
731280304Sjkim */
732280304Sjkim# endif
733160814Ssimon
734280304Sjkim/*
735280304Sjkim * All we really need to do is remove the 'error' state when a thread
736280304Sjkim * detaches
737280304Sjkim */
73855714Skris
739280304SjkimBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
740280304Sjkim{
741280304Sjkim    switch (fdwReason) {
742280304Sjkim    case DLL_PROCESS_ATTACH:
743280304Sjkim        OPENSSL_cpuid_setup();
744280304Sjkim# if defined(_WIN32_WINNT)
745280304Sjkim        {
746280304Sjkim            IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
747280304Sjkim            IMAGE_NT_HEADERS *nt_headers;
748160814Ssimon
749280304Sjkim            if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
750280304Sjkim                nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
751280304Sjkim                                                   + dos_header->e_lfanew);
752280304Sjkim                if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
753280304Sjkim                    hinstDLL !=
754280304Sjkim                    (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
755280304Sjkim                    OPENSSL_NONPIC_relocated = 1;
756280304Sjkim            }
757280304Sjkim        }
758280304Sjkim# endif
759280304Sjkim        break;
760280304Sjkim    case DLL_THREAD_ATTACH:
761280304Sjkim        break;
762280304Sjkim    case DLL_THREAD_DETACH:
763280304Sjkim        break;
764280304Sjkim    case DLL_PROCESS_DETACH:
765280304Sjkim        break;
766280304Sjkim    }
767280304Sjkim    return (TRUE);
768280304Sjkim}
769160814Ssimon#endif
77055714Skris
771160814Ssimon#if defined(_WIN32) && !defined(__CYGWIN__)
772280304Sjkim# include <tchar.h>
773280304Sjkim# include <signal.h>
774280304Sjkim# ifdef __WATCOMC__
775280304Sjkim#  if defined(_UNICODE) || defined(__UNICODE__)
776280304Sjkim#   define _vsntprintf _vsnwprintf
777280304Sjkim#  else
778280304Sjkim#   define _vsntprintf _vsnprintf
779280304Sjkim#  endif
780280304Sjkim# endif
781280304Sjkim# ifdef _MSC_VER
782280304Sjkim#  define alloca _alloca
783280304Sjkim# endif
784109998Smarkm
785280304Sjkim# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
786160814Ssimonint OPENSSL_isservice(void)
787280304Sjkim{
788280304Sjkim    HWINSTA h;
789280304Sjkim    DWORD len;
790280304Sjkim    WCHAR *name;
791280304Sjkim    static union {
792280304Sjkim        void *p;
793280304Sjkim        int (*f) (void);
794280304Sjkim    } _OPENSSL_isservice = {
795280304Sjkim        NULL
796280304Sjkim    };
797142425Snectar
798238405Sjkim    if (_OPENSSL_isservice.p == NULL) {
799280304Sjkim        HANDLE h = GetModuleHandle(NULL);
800280304Sjkim        if (h != NULL)
801280304Sjkim            _OPENSSL_isservice.p = GetProcAddress(h, "_OPENSSL_isservice");
802280304Sjkim        if (_OPENSSL_isservice.p == NULL)
803280304Sjkim            _OPENSSL_isservice.p = (void *)-1;
804238405Sjkim    }
805238405Sjkim
806238405Sjkim    if (_OPENSSL_isservice.p != (void *)-1)
807280304Sjkim        return (*_OPENSSL_isservice.f) ();
808238405Sjkim
809160814Ssimon    h = GetProcessWindowStation();
810280304Sjkim    if (h == NULL)
811280304Sjkim        return -1;
812142425Snectar
813280304Sjkim    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
814280304Sjkim        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
815280304Sjkim        return -1;
816142425Snectar
817280304Sjkim    if (len > 512)
818280304Sjkim        return -1;              /* paranoia */
819280304Sjkim    len++, len &= ~1;           /* paranoia */
820280304Sjkim    name = (WCHAR *)alloca(len + sizeof(WCHAR));
821280304Sjkim    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
822280304Sjkim        return -1;
823142425Snectar
824280304Sjkim    len++, len &= ~1;           /* paranoia */
825280304Sjkim    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
826280304Sjkim#  if 1
827280304Sjkim    /*
828280304Sjkim     * This doesn't cover "interactive" services [working with real
829280304Sjkim     * WinSta0's] nor programs started non-interactively by Task Scheduler
830280304Sjkim     * [those are working with SAWinSta].
831280304Sjkim     */
832280304Sjkim    if (wcsstr(name, L"Service-0x"))
833280304Sjkim        return 1;
834280304Sjkim#  else
835160814Ssimon    /* This covers all non-interactive programs such as services. */
836280304Sjkim    if (!wcsstr(name, L"WinSta0"))
837280304Sjkim        return 1;
838280304Sjkim#  endif
839280304Sjkim    else
840280304Sjkim        return 0;
841160814Ssimon}
842280304Sjkim# else
843280304Sjkimint OPENSSL_isservice(void)
844280304Sjkim{
845280304Sjkim    return 0;
846280304Sjkim}
847280304Sjkim# endif
848142425Snectar
849280304Sjkimvoid OPENSSL_showfatal(const char *fmta, ...)
850280304Sjkim{
851280304Sjkim    va_list ap;
852280304Sjkim    TCHAR buf[256];
853280304Sjkim    const TCHAR *fmt;
854280304Sjkim# ifdef STD_ERROR_HANDLE        /* what a dirty trick! */
855280304Sjkim    HANDLE h;
856142425Snectar
857280304Sjkim    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
858280304Sjkim        GetFileType(h) != FILE_TYPE_UNKNOWN) {
859280304Sjkim        /* must be console application */
860280304Sjkim        va_start(ap, fmta);
861280304Sjkim        vfprintf(stderr, fmta, ap);
862280304Sjkim        va_end(ap);
863280304Sjkim        return;
864160814Ssimon    }
865280304Sjkim# endif
866142425Snectar
867280304Sjkim    if (sizeof(TCHAR) == sizeof(char))
868280304Sjkim        fmt = (const TCHAR *)fmta;
869280304Sjkim    else
870280304Sjkim        do {
871280304Sjkim            int keepgoing;
872280304Sjkim            size_t len_0 = strlen(fmta) + 1, i;
873280304Sjkim            WCHAR *fmtw;
874142425Snectar
875280304Sjkim            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
876280304Sjkim            if (fmtw == NULL) {
877280304Sjkim                fmt = (const TCHAR *)L"no stack?";
878280304Sjkim                break;
879280304Sjkim            }
880280304Sjkim# ifndef OPENSSL_NO_MULTIBYTE
881280304Sjkim            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
882280304Sjkim# endif
883280304Sjkim                for (i = 0; i < len_0; i++)
884280304Sjkim                    fmtw[i] = (WCHAR)fmta[i];
885142425Snectar
886280304Sjkim            for (i = 0; i < len_0; i++) {
887280304Sjkim                if (fmtw[i] == L'%')
888280304Sjkim                    do {
889280304Sjkim                        keepgoing = 0;
890280304Sjkim                        switch (fmtw[i + 1]) {
891280304Sjkim                        case L'0':
892280304Sjkim                        case L'1':
893280304Sjkim                        case L'2':
894280304Sjkim                        case L'3':
895280304Sjkim                        case L'4':
896280304Sjkim                        case L'5':
897280304Sjkim                        case L'6':
898280304Sjkim                        case L'7':
899280304Sjkim                        case L'8':
900280304Sjkim                        case L'9':
901280304Sjkim                        case L'.':
902280304Sjkim                        case L'*':
903280304Sjkim                        case L'-':
904280304Sjkim                            i++;
905280304Sjkim                            keepgoing = 1;
906280304Sjkim                            break;
907280304Sjkim                        case L's':
908280304Sjkim                            fmtw[i + 1] = L'S';
909280304Sjkim                            break;
910280304Sjkim                        case L'S':
911280304Sjkim                            fmtw[i + 1] = L's';
912280304Sjkim                            break;
913280304Sjkim                        case L'c':
914280304Sjkim                            fmtw[i + 1] = L'C';
915280304Sjkim                            break;
916280304Sjkim                        case L'C':
917280304Sjkim                            fmtw[i + 1] = L'c';
918280304Sjkim                            break;
919280304Sjkim                        }
920280304Sjkim                    } while (keepgoing);
921280304Sjkim            }
922280304Sjkim            fmt = (const TCHAR *)fmtw;
923280304Sjkim        } while (0);
924142425Snectar
925280304Sjkim    va_start(ap, fmta);
926280304Sjkim    _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
927280304Sjkim    buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
928280304Sjkim    va_end(ap);
929142425Snectar
930280304Sjkim# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
931160814Ssimon    /* this -------------v--- guards NT-specific calls */
932280304Sjkim    if (check_winnt() && OPENSSL_isservice() > 0) {
933291721Sjkim        HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));
934291721Sjkim
935291721Sjkim        if (hEventLog != NULL) {
936291721Sjkim            const TCHAR *pmsg = buf;
937291721Sjkim
938291721Sjkim            if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,
939291721Sjkim                             1, 0, &pmsg, NULL)) {
940291721Sjkim#if defined(DEBUG)
941291721Sjkim                /*
942291721Sjkim                 * We are in a situation where we tried to report a critical
943291721Sjkim                 * error and this failed for some reason. As a last resort,
944291721Sjkim                 * in debug builds, send output to the debugger or any other
945291721Sjkim                 * tool like DebugView which can monitor the output.
946291721Sjkim                 */
947291721Sjkim                OutputDebugString(pmsg);
948291721Sjkim#endif
949291721Sjkim            }
950291721Sjkim
951291721Sjkim            (void)DeregisterEventSource(hEventLog);
952291721Sjkim        }
953280304Sjkim    } else
954280304Sjkim# endif
955291721Sjkim        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
956160814Ssimon}
957160814Ssimon#else
958280304Sjkimvoid OPENSSL_showfatal(const char *fmta, ...)
959280304Sjkim{
960280304Sjkim    va_list ap;
961142425Snectar
962280304Sjkim    va_start(ap, fmta);
963280304Sjkim    vfprintf(stderr, fmta, ap);
964280304Sjkim    va_end(ap);
965160814Ssimon}
966280304Sjkim
967280304Sjkimint OPENSSL_isservice(void)
968280304Sjkim{
969280304Sjkim    return 0;
970280304Sjkim}
971160814Ssimon#endif
972142425Snectar
973280304Sjkimvoid OpenSSLDie(const char *file, int line, const char *assertion)
974280304Sjkim{
975280304Sjkim    OPENSSL_showfatal
976280304Sjkim        ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
977280304Sjkim         assertion);
978238405Sjkim#if !defined(_WIN32) || defined(__CYGWIN__)
979280304Sjkim    abort();
980238405Sjkim#else
981280304Sjkim    /*
982280304Sjkim     * Win32 abort() customarily shows a dialog, but we just did that...
983280304Sjkim     */
984280304Sjkim    raise(SIGABRT);
985280304Sjkim    _exit(3);
986238405Sjkim#endif
987280304Sjkim}
988142425Snectar
989280304Sjkimvoid *OPENSSL_stderr(void)
990280304Sjkim{
991280304Sjkim    return stderr;
992280304Sjkim}
993246772Sjkim
994246772Sjkimint CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
995280304Sjkim{
996280304Sjkim    size_t i;
997280304Sjkim    const unsigned char *a = in_a;
998280304Sjkim    const unsigned char *b = in_b;
999280304Sjkim    unsigned char x = 0;
1000246772Sjkim
1001280304Sjkim    for (i = 0; i < len; i++)
1002280304Sjkim        x |= a[i] ^ b[i];
1003246772Sjkim
1004280304Sjkim    return x;
1005280304Sjkim}
1006