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
10296341Sdelphij *    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.
61296341Sdelphij *
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).
68296341Sdelphij *
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.
75296341Sdelphij *
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 :-).
90296341Sdelphij * 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)"
93296341Sdelphij *
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.
105296341Sdelphij *
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.
113296341Sdelphij * 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)
121296341Sdelphijstatic 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 */
127296341Sdelphijstatic const char *const lock_names[CRYPTO_NUM_LOCKS] = {
128296341Sdelphij    "<<ERROR>>",
129296341Sdelphij    "err",
130296341Sdelphij    "ex_data",
131296341Sdelphij    "x509",
132296341Sdelphij    "x509_info",
133296341Sdelphij    "x509_pkey",
134296341Sdelphij    "x509_crl",
135296341Sdelphij    "x509_req",
136296341Sdelphij    "dsa",
137296341Sdelphij    "rsa",
138296341Sdelphij    "evp_pkey",
139296341Sdelphij    "x509_store",
140296341Sdelphij    "ssl_ctx",
141296341Sdelphij    "ssl_cert",
142296341Sdelphij    "ssl_session",
143296341Sdelphij    "ssl_sess_cert",
144296341Sdelphij    "ssl",
145296341Sdelphij    "ssl_method",
146296341Sdelphij    "rand",
147296341Sdelphij    "rand2",
148296341Sdelphij    "debug_malloc",
149296341Sdelphij    "BIO",
150296341Sdelphij    "gethostbyname",
151296341Sdelphij    "getservbyname",
152296341Sdelphij    "readdir",
153296341Sdelphij    "RSA_blinding",
154296341Sdelphij    "dh",
155296341Sdelphij    "debug_malloc2",
156296341Sdelphij    "dso",
157296341Sdelphij    "dynlock",
158296341Sdelphij    "engine",
159296341Sdelphij    "ui",
160296341Sdelphij    "ecdsa",
161296341Sdelphij    "ec",
162296341Sdelphij    "ecdh",
163296341Sdelphij    "bn",
164296341Sdelphij    "ec_pre_comp",
165296341Sdelphij    "store",
166296341Sdelphij    "comp",
167296341Sdelphij    "fips",
168296341Sdelphij    "fips2",
169238405Sjkim#if CRYPTO_NUM_LOCKS != 41
170238405Sjkim# error "Inconsistency between crypto.h and cryptlib.c"
171238405Sjkim#endif
172296341Sdelphij};
173238405Sjkim
174296341Sdelphij/*
175296341Sdelphij * This is for applications to allocate new type names in the non-dynamic
176296341Sdelphij * array of lock names.  These are numbered with positive numbers.
177296341Sdelphij */
178296341Sdelphijstatic STACK_OF(OPENSSL_STRING) *app_locks = NULL;
179238405Sjkim
180296341Sdelphij/*
181296341Sdelphij * For applications that want a more dynamic way of handling threads, the
182296341Sdelphij * following stack is used.  These are externally numbered with negative
183296341Sdelphij * numbers.
184296341Sdelphij */
185296341Sdelphijstatic STACK_OF(CRYPTO_dynlock) *dyn_locks = NULL;
186238405Sjkim
187296341Sdelphijstatic void (MS_FAR *locking_callback) (int mode, int type,
188296341Sdelphij                                        const char *file, int line) = 0;
189296341Sdelphijstatic int (MS_FAR *add_lock_callback) (int *pointer, int amount,
190296341Sdelphij                                        int type, const char *file,
191296341Sdelphij                                        int line) = 0;
192238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
193296341Sdelphijstatic unsigned long (MS_FAR *id_callback) (void) = 0;
194238405Sjkim#endif
195296341Sdelphijstatic void (MS_FAR *threadid_callback) (CRYPTO_THREADID *) = 0;
196238405Sjkimstatic struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
197296341Sdelphij (const char *file, int line) = 0;
198296341Sdelphijstatic void (MS_FAR *dynlock_lock_callback) (int mode,
199296341Sdelphij                                             struct CRYPTO_dynlock_value *l,
200296341Sdelphij                                             const char *file, int line) = 0;
201296341Sdelphijstatic void (MS_FAR *dynlock_destroy_callback) (struct CRYPTO_dynlock_value
202296341Sdelphij                                                *l, const char *file,
203296341Sdelphij                                                int line) = 0;
20468651Skris
205238405Sjkimint CRYPTO_get_new_lockid(char *name)
206296341Sdelphij{
207296341Sdelphij    char *str;
208296341Sdelphij    int i;
209238405Sjkim
210238405Sjkim#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16)
211296341Sdelphij    /*
212296341Sdelphij     * A hack to make Visual C++ 5.0 work correctly when linking as a DLL
213296341Sdelphij     * using /MT. Without this, the application cannot use any floating point
214296341Sdelphij     * printf's. It also seems to be needed for Visual C 1.5 (win16)
215296341Sdelphij     */
216296341Sdelphij    SSLeay_MSVC5_hack = (double)name[0] * (double)name[1];
217238405Sjkim#endif
218238405Sjkim
219296341Sdelphij    if ((app_locks == NULL)
220296341Sdelphij        && ((app_locks = sk_OPENSSL_STRING_new_null()) == NULL)) {
221296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
222296341Sdelphij        return (0);
223296341Sdelphij    }
224296341Sdelphij    if ((str = BUF_strdup(name)) == NULL) {
225296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID, ERR_R_MALLOC_FAILURE);
226296341Sdelphij        return (0);
227296341Sdelphij    }
228296341Sdelphij    i = sk_OPENSSL_STRING_push(app_locks, str);
229296341Sdelphij    if (!i)
230296341Sdelphij        OPENSSL_free(str);
231296341Sdelphij    else
232296341Sdelphij        i += CRYPTO_NUM_LOCKS;  /* gap of one :-) */
233296341Sdelphij    return (i);
234296341Sdelphij}
235238405Sjkim
23655714Skrisint CRYPTO_num_locks(void)
237296341Sdelphij{
238296341Sdelphij    return CRYPTO_NUM_LOCKS;
239296341Sdelphij}
24055714Skris
241238405Sjkimint CRYPTO_get_new_dynlockid(void)
242296341Sdelphij{
243296341Sdelphij    int i = 0;
244296341Sdelphij    CRYPTO_dynlock *pointer = NULL;
245238405Sjkim
246296341Sdelphij    if (dynlock_create_callback == NULL) {
247296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,
248296341Sdelphij                  CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK);
249296341Sdelphij        return (0);
250296341Sdelphij    }
251296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
252296341Sdelphij    if ((dyn_locks == NULL)
253296341Sdelphij        && ((dyn_locks = sk_CRYPTO_dynlock_new_null()) == NULL)) {
254296341Sdelphij        CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
255296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
256296341Sdelphij        return (0);
257296341Sdelphij    }
258296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
259238405Sjkim
260296341Sdelphij    pointer = (CRYPTO_dynlock *) OPENSSL_malloc(sizeof(CRYPTO_dynlock));
261296341Sdelphij    if (pointer == NULL) {
262296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
263296341Sdelphij        return (0);
264296341Sdelphij    }
265296341Sdelphij    pointer->references = 1;
266296341Sdelphij    pointer->data = dynlock_create_callback(__FILE__, __LINE__);
267296341Sdelphij    if (pointer->data == NULL) {
268296341Sdelphij        OPENSSL_free(pointer);
269296341Sdelphij        CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID, ERR_R_MALLOC_FAILURE);
270296341Sdelphij        return (0);
271296341Sdelphij    }
272238405Sjkim
273296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
274296341Sdelphij    /* First, try to find an existing empty slot */
275296341Sdelphij    i = sk_CRYPTO_dynlock_find(dyn_locks, NULL);
276296341Sdelphij    /* If there was none, push, thereby creating a new one */
277296341Sdelphij    if (i == -1)
278296341Sdelphij        /*
279296341Sdelphij         * Since sk_push() returns the number of items on the stack, not the
280296341Sdelphij         * location of the pushed item, we need to transform the returned
281296341Sdelphij         * number into a position, by decreasing it.
282296341Sdelphij         */
283296341Sdelphij        i = sk_CRYPTO_dynlock_push(dyn_locks, pointer) - 1;
284296341Sdelphij    else
285296341Sdelphij        /*
286296341Sdelphij         * If we found a place with a NULL pointer, put our pointer in it.
287296341Sdelphij         */
288296341Sdelphij        (void)sk_CRYPTO_dynlock_set(dyn_locks, i, pointer);
289296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
290238405Sjkim
291296341Sdelphij    if (i == -1) {
292296341Sdelphij        dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
293296341Sdelphij        OPENSSL_free(pointer);
294296341Sdelphij    } else
295296341Sdelphij        i += 1;                 /* to avoid 0 */
296296341Sdelphij    return -i;
297296341Sdelphij}
298238405Sjkim
299238405Sjkimvoid CRYPTO_destroy_dynlockid(int i)
300296341Sdelphij{
301296341Sdelphij    CRYPTO_dynlock *pointer = NULL;
302296341Sdelphij    if (i)
303296341Sdelphij        i = -i - 1;
304296341Sdelphij    if (dynlock_destroy_callback == NULL)
305296341Sdelphij        return;
306238405Sjkim
307296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
308238405Sjkim
309296341Sdelphij    if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) {
310296341Sdelphij        CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
311296341Sdelphij        return;
312296341Sdelphij    }
313296341Sdelphij    pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
314296341Sdelphij    if (pointer != NULL) {
315296341Sdelphij        --pointer->references;
316238405Sjkim#ifdef REF_CHECK
317296341Sdelphij        if (pointer->references < 0) {
318296341Sdelphij            fprintf(stderr,
319296341Sdelphij                    "CRYPTO_destroy_dynlockid, bad reference count\n");
320296341Sdelphij            abort();
321296341Sdelphij        } else
322238405Sjkim#endif
323296341Sdelphij        if (pointer->references <= 0) {
324296341Sdelphij            (void)sk_CRYPTO_dynlock_set(dyn_locks, i, NULL);
325296341Sdelphij        } else
326296341Sdelphij            pointer = NULL;
327296341Sdelphij    }
328296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
329238405Sjkim
330296341Sdelphij    if (pointer) {
331296341Sdelphij        dynlock_destroy_callback(pointer->data, __FILE__, __LINE__);
332296341Sdelphij        OPENSSL_free(pointer);
333296341Sdelphij    }
334296341Sdelphij}
335238405Sjkim
336238405Sjkimstruct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i)
337296341Sdelphij{
338296341Sdelphij    CRYPTO_dynlock *pointer = NULL;
339296341Sdelphij    if (i)
340296341Sdelphij        i = -i - 1;
341238405Sjkim
342296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK);
343238405Sjkim
344296341Sdelphij    if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks))
345296341Sdelphij        pointer = sk_CRYPTO_dynlock_value(dyn_locks, i);
346296341Sdelphij    if (pointer)
347296341Sdelphij        pointer->references++;
348238405Sjkim
349296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK);
350238405Sjkim
351296341Sdelphij    if (pointer)
352296341Sdelphij        return pointer->data;
353296341Sdelphij    return NULL;
354296341Sdelphij}
355238405Sjkim
356238405Sjkimstruct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))
357296341Sdelphij (const char *file, int line) {
358296341Sdelphij    return (dynlock_create_callback);
359296341Sdelphij}
360238405Sjkim
361296341Sdelphijvoid (*CRYPTO_get_dynlock_lock_callback(void)) (int mode,
362296341Sdelphij                                                struct CRYPTO_dynlock_value
363296341Sdelphij                                                *l, const char *file,
364296341Sdelphij                                                int line) {
365296341Sdelphij    return (dynlock_lock_callback);
366296341Sdelphij}
367238405Sjkim
368238405Sjkimvoid (*CRYPTO_get_dynlock_destroy_callback(void))
369296341Sdelphij (struct CRYPTO_dynlock_value *l, const char *file, int line) {
370296341Sdelphij    return (dynlock_destroy_callback);
371296341Sdelphij}
372238405Sjkim
373238405Sjkimvoid CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func)
374296341Sdelphij                                         (const char *file, int line))
375296341Sdelphij{
376296341Sdelphij    dynlock_create_callback = func;
377296341Sdelphij}
378238405Sjkim
379296341Sdelphijvoid CRYPTO_set_dynlock_lock_callback(void (*func) (int mode,
380296341Sdelphij                                                    struct
381296341Sdelphij                                                    CRYPTO_dynlock_value *l,
382296341Sdelphij                                                    const char *file,
383296341Sdelphij                                                    int line))
384296341Sdelphij{
385296341Sdelphij    dynlock_lock_callback = func;
386296341Sdelphij}
387238405Sjkim
388238405Sjkimvoid CRYPTO_set_dynlock_destroy_callback(void (*func)
389296341Sdelphij                                          (struct CRYPTO_dynlock_value *l,
390296341Sdelphij                                           const char *file, int line))
391296341Sdelphij{
392296341Sdelphij    dynlock_destroy_callback = func;
393296341Sdelphij}
394238405Sjkim
395296341Sdelphijvoid (*CRYPTO_get_locking_callback(void)) (int mode, int type,
396296341Sdelphij                                           const char *file, int line) {
397296341Sdelphij    return (locking_callback);
398296341Sdelphij}
399238405Sjkim
400296341Sdelphijint (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
401296341Sdelphij                                           const char *file, int line) {
402296341Sdelphij    return (add_lock_callback);
403296341Sdelphij}
40455714Skris
405296341Sdelphijvoid CRYPTO_set_locking_callback(void (*func) (int mode, int type,
406296341Sdelphij                                               const char *file, int line))
407296341Sdelphij{
408296341Sdelphij    /*
409296341Sdelphij     * Calling this here ensures initialisation before any threads are
410296341Sdelphij     * started.
411296341Sdelphij     */
412296341Sdelphij    OPENSSL_init();
413296341Sdelphij    locking_callback = func;
414296341Sdelphij}
41555714Skris
416296341Sdelphijvoid CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
417296341Sdelphij                                               const char *file, int line))
418296341Sdelphij{
419296341Sdelphij    add_lock_callback = func;
420296341Sdelphij}
42155714Skris
422296341Sdelphij/*
423296341Sdelphij * the memset() here and in set_pointer() seem overkill, but for the sake of
424296341Sdelphij * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause
425296341Sdelphij * two "equal" THREADID structs to not be memcmp()-identical.
426296341Sdelphij */
427238405Sjkimvoid CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
428296341Sdelphij{
429296341Sdelphij    memset(id, 0, sizeof(*id));
430296341Sdelphij    id->val = val;
431296341Sdelphij}
432238405Sjkim
433238405Sjkimstatic const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
434296341Sdelphij
435238405Sjkimvoid CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
436296341Sdelphij{
437296341Sdelphij    unsigned char *dest = (void *)&id->val;
438296341Sdelphij    unsigned int accum = 0;
439296341Sdelphij    unsigned char dnum = sizeof(id->val);
440238405Sjkim
441296341Sdelphij    memset(id, 0, sizeof(*id));
442296341Sdelphij    id->ptr = ptr;
443296341Sdelphij    if (sizeof(id->val) >= sizeof(id->ptr)) {
444296341Sdelphij        /*
445296341Sdelphij         * 'ptr' can be embedded in 'val' without loss of uniqueness
446296341Sdelphij         */
447296341Sdelphij        id->val = (unsigned long)id->ptr;
448296341Sdelphij        return;
449296341Sdelphij    }
450296341Sdelphij    /*
451296341Sdelphij     * hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a
452296341Sdelphij     * linear function over the bytes in 'ptr', the co-efficients of which
453296341Sdelphij     * are a sequence of low-primes (hash_coeffs is an 8-element cycle) - the
454296341Sdelphij     * starting prime for the sequence varies for each byte of 'val' (unique
455296341Sdelphij     * polynomials unless pointers are >64-bit). For added spice, the totals
456296341Sdelphij     * accumulate rather than restarting from zero, and the index of the
457296341Sdelphij     * 'val' byte is added each time (position dependence). If I was a
458296341Sdelphij     * black-belt, I'd scan big-endian pointers in reverse to give low-order
459296341Sdelphij     * bits more play, but this isn't crypto and I'd prefer nobody mistake it
460296341Sdelphij     * as such. Plus I'm lazy.
461296341Sdelphij     */
462296341Sdelphij    while (dnum--) {
463296341Sdelphij        const unsigned char *src = (void *)&id->ptr;
464296341Sdelphij        unsigned char snum = sizeof(id->ptr);
465296341Sdelphij        while (snum--)
466296341Sdelphij            accum += *(src++) * hash_coeffs[(snum + dnum) & 7];
467296341Sdelphij        accum += dnum;
468296341Sdelphij        *(dest++) = accum & 255;
469296341Sdelphij    }
470296341Sdelphij}
471238405Sjkim
472296341Sdelphijint CRYPTO_THREADID_set_callback(void (*func) (CRYPTO_THREADID *))
473296341Sdelphij{
474296341Sdelphij    if (threadid_callback)
475296341Sdelphij        return 0;
476296341Sdelphij    threadid_callback = func;
477296341Sdelphij    return 1;
478296341Sdelphij}
479238405Sjkim
480296341Sdelphijvoid (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *) {
481296341Sdelphij    return threadid_callback;
482296341Sdelphij}
483238405Sjkim
484238405Sjkimvoid CRYPTO_THREADID_current(CRYPTO_THREADID *id)
485296341Sdelphij{
486296341Sdelphij    if (threadid_callback) {
487296341Sdelphij        threadid_callback(id);
488296341Sdelphij        return;
489296341Sdelphij    }
490238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
491296341Sdelphij    /* If the deprecated callback was set, fall back to that */
492296341Sdelphij    if (id_callback) {
493296341Sdelphij        CRYPTO_THREADID_set_numeric(id, id_callback());
494296341Sdelphij        return;
495296341Sdelphij    }
496238405Sjkim#endif
497296341Sdelphij    /* Else pick a backup */
498238405Sjkim#ifdef OPENSSL_SYS_WIN16
499296341Sdelphij    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask());
500238405Sjkim#elif defined(OPENSSL_SYS_WIN32)
501296341Sdelphij    CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
502238405Sjkim#elif defined(OPENSSL_SYS_BEOS)
503296341Sdelphij    CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
504238405Sjkim#else
505296341Sdelphij    /* For everything else, default to using the address of 'errno' */
506296341Sdelphij    CRYPTO_THREADID_set_pointer(id, (void *)&errno);
507238405Sjkim#endif
508296341Sdelphij}
509238405Sjkim
510238405Sjkimint CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
511296341Sdelphij{
512296341Sdelphij    return memcmp(a, b, sizeof(*a));
513296341Sdelphij}
514238405Sjkim
515238405Sjkimvoid CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
516296341Sdelphij{
517296341Sdelphij    memcpy(dest, src, sizeof(*src));
518296341Sdelphij}
519238405Sjkim
520238405Sjkimunsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
521296341Sdelphij{
522296341Sdelphij    return id->val;
523296341Sdelphij}
524238405Sjkim
525238405Sjkim#ifndef OPENSSL_NO_DEPRECATED
526296341Sdelphijunsigned long (*CRYPTO_get_id_callback(void)) (void) {
527296341Sdelphij    return (id_callback);
528296341Sdelphij}
52955714Skris
530296341Sdelphijvoid CRYPTO_set_id_callback(unsigned long (*func) (void))
531296341Sdelphij{
532296341Sdelphij    id_callback = func;
533296341Sdelphij}
53455714Skris
53555714Skrisunsigned long CRYPTO_thread_id(void)
536296341Sdelphij{
537296341Sdelphij    unsigned long ret = 0;
53855714Skris
539296341Sdelphij    if (id_callback == NULL) {
540296341Sdelphij# ifdef OPENSSL_SYS_WIN16
541296341Sdelphij        ret = (unsigned long)GetCurrentTask();
542296341Sdelphij# elif defined(OPENSSL_SYS_WIN32)
543296341Sdelphij        ret = (unsigned long)GetCurrentThreadId();
544296341Sdelphij# elif defined(GETPID_IS_MEANINGLESS)
545296341Sdelphij        ret = 1L;
546296341Sdelphij# elif defined(OPENSSL_SYS_BEOS)
547296341Sdelphij        ret = (unsigned long)find_thread(NULL);
548296341Sdelphij# else
549296341Sdelphij        ret = (unsigned long)getpid();
550296341Sdelphij# endif
551296341Sdelphij    } else
552296341Sdelphij        ret = id_callback();
553296341Sdelphij    return (ret);
554296341Sdelphij}
55555714Skris#endif
55655714Skris
55755714Skrisvoid CRYPTO_lock(int mode, int type, const char *file, int line)
558296341Sdelphij{
55955714Skris#ifdef LOCK_DEBUG
560296341Sdelphij    {
561296341Sdelphij        CRYPTO_THREADID id;
562296341Sdelphij        char *rw_text, *operation_text;
56355714Skris
564296341Sdelphij        if (mode & CRYPTO_LOCK)
565296341Sdelphij            operation_text = "lock  ";
566296341Sdelphij        else if (mode & CRYPTO_UNLOCK)
567296341Sdelphij            operation_text = "unlock";
568296341Sdelphij        else
569296341Sdelphij            operation_text = "ERROR ";
57055714Skris
571296341Sdelphij        if (mode & CRYPTO_READ)
572296341Sdelphij            rw_text = "r";
573296341Sdelphij        else if (mode & CRYPTO_WRITE)
574296341Sdelphij            rw_text = "w";
575296341Sdelphij        else
576296341Sdelphij            rw_text = "ERROR";
57755714Skris
578296341Sdelphij        CRYPTO_THREADID_current(&id);
579296341Sdelphij        fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
580296341Sdelphij                CRYPTO_THREADID_hash(&id), rw_text, operation_text,
581296341Sdelphij                CRYPTO_get_lock_name(type), file, line);
582296341Sdelphij    }
58355714Skris#endif
584296341Sdelphij    if (type < 0) {
585296341Sdelphij        if (dynlock_lock_callback != NULL) {
586296341Sdelphij            struct CRYPTO_dynlock_value *pointer
587296341Sdelphij                = CRYPTO_get_dynlock_value(type);
588238405Sjkim
589296341Sdelphij            OPENSSL_assert(pointer != NULL);
590238405Sjkim
591296341Sdelphij            dynlock_lock_callback(mode, pointer, file, line);
592238405Sjkim
593296341Sdelphij            CRYPTO_destroy_dynlockid(type);
594296341Sdelphij        }
595296341Sdelphij    } else if (locking_callback != NULL)
596296341Sdelphij        locking_callback(mode, type, file, line);
597296341Sdelphij}
59855714Skris
59955714Skrisint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
600296341Sdelphij                    int line)
601296341Sdelphij{
602296341Sdelphij    int ret = 0;
60355714Skris
604296341Sdelphij    if (add_lock_callback != NULL) {
60555714Skris#ifdef LOCK_DEBUG
606296341Sdelphij        int before = *pointer;
60755714Skris#endif
60855714Skris
609296341Sdelphij        ret = add_lock_callback(pointer, amount, type, file, line);
61055714Skris#ifdef LOCK_DEBUG
611296341Sdelphij        {
612296341Sdelphij            CRYPTO_THREADID id;
613296341Sdelphij            CRYPTO_THREADID_current(&id);
614296341Sdelphij            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
615296341Sdelphij                    CRYPTO_THREADID_hash(&id), before, amount, ret,
616296341Sdelphij                    CRYPTO_get_lock_name(type), file, line);
617296341Sdelphij        }
61855714Skris#endif
619296341Sdelphij    } else {
620296341Sdelphij        CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
62155714Skris
622296341Sdelphij        ret = *pointer + amount;
62355714Skris#ifdef LOCK_DEBUG
624296341Sdelphij        {
625296341Sdelphij            CRYPTO_THREADID id;
626296341Sdelphij            CRYPTO_THREADID_current(&id);
627296341Sdelphij            fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
628296341Sdelphij                    CRYPTO_THREADID_hash(&id),
629296341Sdelphij                    *pointer, amount, ret,
630296341Sdelphij                    CRYPTO_get_lock_name(type), file, line);
631296341Sdelphij        }
63255714Skris#endif
633296341Sdelphij        *pointer = ret;
634296341Sdelphij        CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
635296341Sdelphij    }
636296341Sdelphij    return (ret);
637296341Sdelphij}
63855714Skris
639238405Sjkimconst char *CRYPTO_get_lock_name(int type)
640296341Sdelphij{
641296341Sdelphij    if (type < 0)
642296341Sdelphij        return ("dynamic");
643296341Sdelphij    else if (type < CRYPTO_NUM_LOCKS)
644296341Sdelphij        return (lock_names[type]);
645296341Sdelphij    else if (type - CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
646296341Sdelphij        return ("ERROR");
647296341Sdelphij    else
648296341Sdelphij        return (sk_OPENSSL_STRING_value(app_locks, type - CRYPTO_NUM_LOCKS));
649296341Sdelphij}
650238405Sjkim
651296341Sdelphij#if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
652296341Sdelphij        defined(__INTEL__) || \
653296341Sdelphij        defined(__x86_64) || defined(__x86_64__) || \
654296341Sdelphij        defined(_M_AMD64) || defined(_M_X64)
65555714Skris
656296341Sdelphijunsigned int OPENSSL_ia32cap_P[2];
657238405Sjkimunsigned long *OPENSSL_ia32cap_loc(void)
658296341Sdelphij{
659296341Sdelphij    if (sizeof(long) == 4)
660296341Sdelphij        /*
661296341Sdelphij         * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
662296341Sdelphij         * clear second element to maintain the illusion that vector
663296341Sdelphij         * is 32-bit.
664296341Sdelphij         */
665296341Sdelphij        OPENSSL_ia32cap_P[1] = 0;
666238405Sjkim    return (unsigned long *)OPENSSL_ia32cap_P;
667238405Sjkim}
668160814Ssimon
669296341Sdelphij# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
670296341Sdelphij#  define OPENSSL_CPUID_SETUP
671296341Sdelphij#  if defined(_WIN32)
672238405Sjkimtypedef unsigned __int64 IA32CAP;
673296341Sdelphij#  else
674238405Sjkimtypedef unsigned long long IA32CAP;
675296341Sdelphij#  endif
676160814Ssimonvoid OPENSSL_cpuid_setup(void)
677296341Sdelphij{
678296341Sdelphij    static int trigger = 0;
679296341Sdelphij    IA32CAP OPENSSL_ia32_cpuid(void);
680296341Sdelphij    IA32CAP vec;
681296341Sdelphij    char *env;
682160814Ssimon
683296341Sdelphij    if (trigger)
684296341Sdelphij        return;
685160814Ssimon
686296341Sdelphij    trigger = 1;
687296341Sdelphij    if ((env = getenv("OPENSSL_ia32cap"))) {
688296341Sdelphij        int off = (env[0] == '~') ? 1 : 0;
689296341Sdelphij#  if defined(_WIN32)
690296341Sdelphij        if (!sscanf(env + off, "%I64i", &vec))
691296341Sdelphij            vec = strtoul(env + off, NULL, 0);
692296341Sdelphij#  else
693296341Sdelphij        if (!sscanf(env + off, "%lli", (long long *)&vec))
694296341Sdelphij            vec = strtoul(env + off, NULL, 0);
695296341Sdelphij#  endif
696296341Sdelphij        if (off)
697296341Sdelphij            vec = OPENSSL_ia32_cpuid() & ~vec;
698296341Sdelphij    } else
699296341Sdelphij        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     */
706296341Sdelphij    OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10);
707296341Sdelphij    OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32);
708160814Ssimon}
709296341Sdelphij# endif
710160814Ssimon
711160814Ssimon#else
712296341Sdelphijunsigned long *OPENSSL_ia32cap_loc(void)
713296341Sdelphij{
714296341Sdelphij    return NULL;
715296341Sdelphij}
716160814Ssimon#endif
717160814Ssimonint OPENSSL_NONPIC_relocated = 0;
718238405Sjkim#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
719296341Sdelphijvoid OPENSSL_cpuid_setup(void)
720296341Sdelphij{
721296341Sdelphij}
722160814Ssimon#endif
723160814Ssimon
724160814Ssimon#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
725296341Sdelphij# ifdef __CYGWIN__
726160814Ssimon/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
727296341Sdelphij#  include <windows.h>
728296341Sdelphij/*
729296341Sdelphij * this has side-effect of _WIN32 getting defined, which otherwise is
730296341Sdelphij * mutually exclusive with __CYGWIN__...
731296341Sdelphij */
732296341Sdelphij# endif
733160814Ssimon
734296341Sdelphij/*
735296341Sdelphij * All we really need to do is remove the 'error' state when a thread
736296341Sdelphij * detaches
737296341Sdelphij */
73855714Skris
739296341SdelphijBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
740296341Sdelphij{
741296341Sdelphij    switch (fdwReason) {
742296341Sdelphij    case DLL_PROCESS_ATTACH:
743296341Sdelphij        OPENSSL_cpuid_setup();
744296341Sdelphij# if defined(_WIN32_WINNT)
745296341Sdelphij        {
746296341Sdelphij            IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
747296341Sdelphij            IMAGE_NT_HEADERS *nt_headers;
748160814Ssimon
749296341Sdelphij            if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
750296341Sdelphij                nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
751296341Sdelphij                                                   + dos_header->e_lfanew);
752296341Sdelphij                if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
753296341Sdelphij                    hinstDLL !=
754296341Sdelphij                    (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
755296341Sdelphij                    OPENSSL_NONPIC_relocated = 1;
756296341Sdelphij            }
757296341Sdelphij        }
758296341Sdelphij# endif
759296341Sdelphij        break;
760296341Sdelphij    case DLL_THREAD_ATTACH:
761296341Sdelphij        break;
762296341Sdelphij    case DLL_THREAD_DETACH:
763296341Sdelphij        break;
764296341Sdelphij    case DLL_PROCESS_DETACH:
765296341Sdelphij        break;
766296341Sdelphij    }
767296341Sdelphij    return (TRUE);
768296341Sdelphij}
769160814Ssimon#endif
77055714Skris
771160814Ssimon#if defined(_WIN32) && !defined(__CYGWIN__)
772296341Sdelphij# include <tchar.h>
773296341Sdelphij# include <signal.h>
774296341Sdelphij# ifdef __WATCOMC__
775296341Sdelphij#  if defined(_UNICODE) || defined(__UNICODE__)
776296341Sdelphij#   define _vsntprintf _vsnwprintf
777296341Sdelphij#  else
778296341Sdelphij#   define _vsntprintf _vsnprintf
779296341Sdelphij#  endif
780296341Sdelphij# endif
781296341Sdelphij# ifdef _MSC_VER
782296341Sdelphij#  define alloca _alloca
783296341Sdelphij# endif
784109998Smarkm
785296341Sdelphij# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
786160814Ssimonint OPENSSL_isservice(void)
787296341Sdelphij{
788296341Sdelphij    HWINSTA h;
789296341Sdelphij    DWORD len;
790296341Sdelphij    WCHAR *name;
791296341Sdelphij    static union {
792296341Sdelphij        void *p;
793296341Sdelphij        int (*f) (void);
794296341Sdelphij    } _OPENSSL_isservice = {
795296341Sdelphij        NULL
796296341Sdelphij    };
797142425Snectar
798238405Sjkim    if (_OPENSSL_isservice.p == NULL) {
799296341Sdelphij        HANDLE h = GetModuleHandle(NULL);
800296341Sdelphij        if (h != NULL)
801296341Sdelphij            _OPENSSL_isservice.p = GetProcAddress(h, "_OPENSSL_isservice");
802296341Sdelphij        if (_OPENSSL_isservice.p == NULL)
803296341Sdelphij            _OPENSSL_isservice.p = (void *)-1;
804238405Sjkim    }
805238405Sjkim
806238405Sjkim    if (_OPENSSL_isservice.p != (void *)-1)
807296341Sdelphij        return (*_OPENSSL_isservice.f) ();
808238405Sjkim
809160814Ssimon    h = GetProcessWindowStation();
810296341Sdelphij    if (h == NULL)
811296341Sdelphij        return -1;
812142425Snectar
813296341Sdelphij    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
814296341Sdelphij        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
815296341Sdelphij        return -1;
816142425Snectar
817296341Sdelphij    if (len > 512)
818296341Sdelphij        return -1;              /* paranoia */
819296341Sdelphij    len++, len &= ~1;           /* paranoia */
820296341Sdelphij    name = (WCHAR *)alloca(len + sizeof(WCHAR));
821296341Sdelphij    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
822296341Sdelphij        return -1;
823142425Snectar
824296341Sdelphij    len++, len &= ~1;           /* paranoia */
825296341Sdelphij    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
826296341Sdelphij#  if 1
827296341Sdelphij    /*
828296341Sdelphij     * This doesn't cover "interactive" services [working with real
829296341Sdelphij     * WinSta0's] nor programs started non-interactively by Task Scheduler
830296341Sdelphij     * [those are working with SAWinSta].
831296341Sdelphij     */
832296341Sdelphij    if (wcsstr(name, L"Service-0x"))
833296341Sdelphij        return 1;
834296341Sdelphij#  else
835160814Ssimon    /* This covers all non-interactive programs such as services. */
836296341Sdelphij    if (!wcsstr(name, L"WinSta0"))
837296341Sdelphij        return 1;
838296341Sdelphij#  endif
839296341Sdelphij    else
840296341Sdelphij        return 0;
841160814Ssimon}
842296341Sdelphij# else
843296341Sdelphijint OPENSSL_isservice(void)
844296341Sdelphij{
845296341Sdelphij    return 0;
846296341Sdelphij}
847296341Sdelphij# endif
848142425Snectar
849296341Sdelphijvoid OPENSSL_showfatal(const char *fmta, ...)
850296341Sdelphij{
851296341Sdelphij    va_list ap;
852296341Sdelphij    TCHAR buf[256];
853296341Sdelphij    const TCHAR *fmt;
854296341Sdelphij# ifdef STD_ERROR_HANDLE        /* what a dirty trick! */
855296341Sdelphij    HANDLE h;
856142425Snectar
857296341Sdelphij    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
858296341Sdelphij        GetFileType(h) != FILE_TYPE_UNKNOWN) {
859296341Sdelphij        /* must be console application */
860296341Sdelphij        va_start(ap, fmta);
861296341Sdelphij        vfprintf(stderr, fmta, ap);
862296341Sdelphij        va_end(ap);
863296341Sdelphij        return;
864160814Ssimon    }
865296341Sdelphij# endif
866142425Snectar
867296341Sdelphij    if (sizeof(TCHAR) == sizeof(char))
868296341Sdelphij        fmt = (const TCHAR *)fmta;
869296341Sdelphij    else
870296341Sdelphij        do {
871296341Sdelphij            int keepgoing;
872296341Sdelphij            size_t len_0 = strlen(fmta) + 1, i;
873296341Sdelphij            WCHAR *fmtw;
874142425Snectar
875296341Sdelphij            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
876296341Sdelphij            if (fmtw == NULL) {
877296341Sdelphij                fmt = (const TCHAR *)L"no stack?";
878296341Sdelphij                break;
879296341Sdelphij            }
880296341Sdelphij# ifndef OPENSSL_NO_MULTIBYTE
881296341Sdelphij            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
882296341Sdelphij# endif
883296341Sdelphij                for (i = 0; i < len_0; i++)
884296341Sdelphij                    fmtw[i] = (WCHAR)fmta[i];
885142425Snectar
886296341Sdelphij            for (i = 0; i < len_0; i++) {
887296341Sdelphij                if (fmtw[i] == L'%')
888296341Sdelphij                    do {
889296341Sdelphij                        keepgoing = 0;
890296341Sdelphij                        switch (fmtw[i + 1]) {
891296341Sdelphij                        case L'0':
892296341Sdelphij                        case L'1':
893296341Sdelphij                        case L'2':
894296341Sdelphij                        case L'3':
895296341Sdelphij                        case L'4':
896296341Sdelphij                        case L'5':
897296341Sdelphij                        case L'6':
898296341Sdelphij                        case L'7':
899296341Sdelphij                        case L'8':
900296341Sdelphij                        case L'9':
901296341Sdelphij                        case L'.':
902296341Sdelphij                        case L'*':
903296341Sdelphij                        case L'-':
904296341Sdelphij                            i++;
905296341Sdelphij                            keepgoing = 1;
906296341Sdelphij                            break;
907296341Sdelphij                        case L's':
908296341Sdelphij                            fmtw[i + 1] = L'S';
909296341Sdelphij                            break;
910296341Sdelphij                        case L'S':
911296341Sdelphij                            fmtw[i + 1] = L's';
912296341Sdelphij                            break;
913296341Sdelphij                        case L'c':
914296341Sdelphij                            fmtw[i + 1] = L'C';
915296341Sdelphij                            break;
916296341Sdelphij                        case L'C':
917296341Sdelphij                            fmtw[i + 1] = L'c';
918296341Sdelphij                            break;
919296341Sdelphij                        }
920296341Sdelphij                    } while (keepgoing);
921296341Sdelphij            }
922296341Sdelphij            fmt = (const TCHAR *)fmtw;
923296341Sdelphij        } while (0);
924142425Snectar
925296341Sdelphij    va_start(ap, fmta);
926296341Sdelphij    _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
927296341Sdelphij    buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
928296341Sdelphij    va_end(ap);
929142425Snectar
930296341Sdelphij# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
931160814Ssimon    /* this -------------v--- guards NT-specific calls */
932296341Sdelphij    if (check_winnt() && OPENSSL_isservice() > 0) {
933296341Sdelphij        HANDLE h = RegisterEventSource(0, _T("OPENSSL"));
934296341Sdelphij        const TCHAR *pmsg = buf;
935296341Sdelphij        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0);
936296341Sdelphij        DeregisterEventSource(h);
937296341Sdelphij    } else
938296341Sdelphij# endif
939296341Sdelphij        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP);
940160814Ssimon}
941160814Ssimon#else
942296341Sdelphijvoid OPENSSL_showfatal(const char *fmta, ...)
943296341Sdelphij{
944296341Sdelphij    va_list ap;
945142425Snectar
946296341Sdelphij    va_start(ap, fmta);
947296341Sdelphij    vfprintf(stderr, fmta, ap);
948296341Sdelphij    va_end(ap);
949160814Ssimon}
950296341Sdelphij
951296341Sdelphijint OPENSSL_isservice(void)
952296341Sdelphij{
953296341Sdelphij    return 0;
954296341Sdelphij}
955160814Ssimon#endif
956142425Snectar
957296341Sdelphijvoid OpenSSLDie(const char *file, int line, const char *assertion)
958296341Sdelphij{
959296341Sdelphij    OPENSSL_showfatal
960296341Sdelphij        ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
961296341Sdelphij         assertion);
962238405Sjkim#if !defined(_WIN32) || defined(__CYGWIN__)
963296341Sdelphij    abort();
964238405Sjkim#else
965296341Sdelphij    /*
966296341Sdelphij     * Win32 abort() customarily shows a dialog, but we just did that...
967296341Sdelphij     */
968296341Sdelphij    raise(SIGABRT);
969296341Sdelphij    _exit(3);
970238405Sjkim#endif
971296341Sdelphij}
972142425Snectar
973296341Sdelphijvoid *OPENSSL_stderr(void)
974296341Sdelphij{
975296341Sdelphij    return stderr;
976296341Sdelphij}
977246772Sjkim
978246772Sjkimint CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
979296341Sdelphij{
980296341Sdelphij    size_t i;
981296341Sdelphij    const unsigned char *a = in_a;
982296341Sdelphij    const unsigned char *b = in_b;
983296341Sdelphij    unsigned char x = 0;
984246772Sjkim
985296341Sdelphij    for (i = 0; i < len; i++)
986296341Sdelphij        x |= a[i] ^ b[i];
987246772Sjkim
988296341Sdelphij    return x;
989296341Sdelphij}
990