155714Skris/* crypto/cryptlib.c */
2160814Ssimon/* ====================================================================
3160814Ssimon * Copyright (c) 1998-2003 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
10296465Sdelphij *    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.
61296465Sdelphij *
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).
68296465Sdelphij *
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.
75296465Sdelphij *
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 :-).
90296465Sdelphij * 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)"
93296465Sdelphij *
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.
105296465Sdelphij *
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.
113296465Sdelphij * 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)
121296465Sdelphijstatic double SSLeay_MSVC5_hack = 0.0; /* and for VC1.5 */
12255714Skris#endif
12355714Skris
124296465Sdelphijstatic void (MS_FAR *locking_callback) (int mode, int type,
125296465Sdelphij                                        const char *file, int line) = NULL;
126296465Sdelphijstatic int (MS_FAR *add_lock_callback) (int *pointer, int amount,
127296465Sdelphij                                        int type, const char *file,
128296465Sdelphij                                        int line) = NULL;
129296465Sdelphijstatic unsigned long (MS_FAR *id_callback) (void) = NULL;
13068651Skris
13155714Skrisint CRYPTO_num_locks(void)
132296465Sdelphij{
133296465Sdelphij    return CRYPTO_NUM_LOCKS;
134296465Sdelphij}
13555714Skris
136296465Sdelphijvoid (*CRYPTO_get_locking_callback(void)) (int mode, int type,
137296465Sdelphij                                           const char *file, int line) {
138296465Sdelphij    return (locking_callback);
139296465Sdelphij}
14055714Skris
141296465Sdelphijint (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type,
142296465Sdelphij                                           const char *file, int line) {
143296465Sdelphij    return (add_lock_callback);
144296465Sdelphij}
14555714Skris
146296465Sdelphijvoid CRYPTO_set_locking_callback(void (*func) (int mode, int type,
147296465Sdelphij                                               const char *file, int line))
148296465Sdelphij{
149296465Sdelphij    locking_callback = func;
150296465Sdelphij}
15155714Skris
152296465Sdelphijvoid CRYPTO_set_add_lock_callback(int (*func) (int *num, int mount, int type,
153296465Sdelphij                                               const char *file, int line))
154296465Sdelphij{
155296465Sdelphij    add_lock_callback = func;
156296465Sdelphij}
15755714Skris
158296465Sdelphijunsigned long (*CRYPTO_get_id_callback(void)) (void) {
159296465Sdelphij    return (id_callback);
160296465Sdelphij}
16155714Skris
162296465Sdelphijvoid CRYPTO_set_id_callback(unsigned long (*func) (void))
163296465Sdelphij{
164296465Sdelphij    id_callback = func;
165296465Sdelphij}
16655714Skris
16755714Skrisunsigned long CRYPTO_thread_id(void)
168296465Sdelphij{
169296465Sdelphij    unsigned long ret = 0;
17055714Skris
171296465Sdelphij    if (id_callback == NULL) {
172109998Smarkm#ifdef OPENSSL_SYS_WIN16
173296465Sdelphij        ret = (unsigned long)GetCurrentTask();
174109998Smarkm#elif defined(OPENSSL_SYS_WIN32)
175296465Sdelphij        ret = (unsigned long)GetCurrentThreadId();
17659191Skris#elif defined(GETPID_IS_MEANINGLESS)
177296465Sdelphij        ret = 1L;
17855714Skris#else
179296465Sdelphij        ret = (unsigned long)getpid();
18055714Skris#endif
181296465Sdelphij    } else
182296465Sdelphij        ret = id_callback();
183296465Sdelphij    return (ret);
184296465Sdelphij}
18555714Skris
186296465Sdelphijstatic void (*do_dynlock_cb) (int mode, int type, const char *file, int line);
187194206Ssimon
188296465Sdelphijvoid int_CRYPTO_set_do_dynlock_callback(void (*dyn_cb)
189296465Sdelphij                                         (int mode, int type,
190296465Sdelphij                                          const char *file, int line))
191296465Sdelphij{
192296465Sdelphij    do_dynlock_cb = dyn_cb;
193296465Sdelphij}
194194206Ssimon
19555714Skrisvoid CRYPTO_lock(int mode, int type, const char *file, int line)
196296465Sdelphij{
19755714Skris#ifdef LOCK_DEBUG
198296465Sdelphij    {
199296465Sdelphij        char *rw_text, *operation_text;
20055714Skris
201296465Sdelphij        if (mode & CRYPTO_LOCK)
202296465Sdelphij            operation_text = "lock  ";
203296465Sdelphij        else if (mode & CRYPTO_UNLOCK)
204296465Sdelphij            operation_text = "unlock";
205296465Sdelphij        else
206296465Sdelphij            operation_text = "ERROR ";
20755714Skris
208296465Sdelphij        if (mode & CRYPTO_READ)
209296465Sdelphij            rw_text = "r";
210296465Sdelphij        else if (mode & CRYPTO_WRITE)
211296465Sdelphij            rw_text = "w";
212296465Sdelphij        else
213296465Sdelphij            rw_text = "ERROR";
21455714Skris
215296465Sdelphij        fprintf(stderr, "lock:%08lx:(%s)%s %-18s %s:%d\n",
216296465Sdelphij                CRYPTO_thread_id(), rw_text, operation_text,
217296465Sdelphij                CRYPTO_get_lock_name(type), file, line);
218296465Sdelphij    }
21955714Skris#endif
220296465Sdelphij    if (type < 0) {
221296465Sdelphij        if (do_dynlock_cb)
222296465Sdelphij            do_dynlock_cb(mode, type, file, line);
223296465Sdelphij    } else if (locking_callback != NULL)
224296465Sdelphij        locking_callback(mode, type, file, line);
225296465Sdelphij}
22655714Skris
22755714Skrisint CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
228296465Sdelphij                    int line)
229296465Sdelphij{
230296465Sdelphij    int ret = 0;
23155714Skris
232296465Sdelphij    if (add_lock_callback != NULL) {
23355714Skris#ifdef LOCK_DEBUG
234296465Sdelphij        int before = *pointer;
23555714Skris#endif
23655714Skris
237296465Sdelphij        ret = add_lock_callback(pointer, amount, type, file, line);
23855714Skris#ifdef LOCK_DEBUG
239296465Sdelphij        fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
240296465Sdelphij                CRYPTO_thread_id(),
241296465Sdelphij                before, amount, ret, CRYPTO_get_lock_name(type), file, line);
24255714Skris#endif
243296465Sdelphij    } else {
244296465Sdelphij        CRYPTO_lock(CRYPTO_LOCK | CRYPTO_WRITE, type, file, line);
24555714Skris
246296465Sdelphij        ret = *pointer + amount;
24755714Skris#ifdef LOCK_DEBUG
248296465Sdelphij        fprintf(stderr, "ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
249296465Sdelphij                CRYPTO_thread_id(),
250296465Sdelphij                *pointer, amount, ret,
251296465Sdelphij                CRYPTO_get_lock_name(type), file, line);
25255714Skris#endif
253296465Sdelphij        *pointer = ret;
254296465Sdelphij        CRYPTO_lock(CRYPTO_UNLOCK | CRYPTO_WRITE, type, file, line);
255296465Sdelphij    }
256296465Sdelphij    return (ret);
257296465Sdelphij}
25855714Skris
259296465Sdelphij#if     defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
260296465Sdelphij        defined(__INTEL__) || \
261296465Sdelphij        defined(__x86_64) || defined(__x86_64__) || \
262296465Sdelphij        defined(_M_AMD64) || defined(_M_X64)
26355714Skris
264296465Sdelphijunsigned long OPENSSL_ia32cap_P = 0;
265296465Sdelphijunsigned long *OPENSSL_ia32cap_loc(void)
266296465Sdelphij{
267296465Sdelphij    return &OPENSSL_ia32cap_P;
268296465Sdelphij}
269160814Ssimon
270296465Sdelphij# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
271296465Sdelphij#  define OPENSSL_CPUID_SETUP
272160814Ssimonvoid OPENSSL_cpuid_setup(void)
273296465Sdelphij{
274296465Sdelphij    static int trigger = 0;
275296465Sdelphij    unsigned long OPENSSL_ia32_cpuid(void);
276296465Sdelphij    char *env;
277160814Ssimon
278296465Sdelphij    if (trigger)
279296465Sdelphij        return;
280160814Ssimon
281296465Sdelphij    trigger = 1;
282296465Sdelphij    if ((env = getenv("OPENSSL_ia32cap")))
283296465Sdelphij        OPENSSL_ia32cap_P = strtoul(env, NULL, 0) | (1 << 10);
284160814Ssimon    else
285296465Sdelphij        OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid() | (1 << 10);
286160814Ssimon    /*
287160814Ssimon     * |(1<<10) sets a reserved bit to signal that variable
288160814Ssimon     * was initialized already... This is to avoid interference
289160814Ssimon     * with cpuid snippets in ELF .init segment.
290160814Ssimon     */
291160814Ssimon}
292296465Sdelphij# endif
293160814Ssimon
294160814Ssimon#else
295296465Sdelphijunsigned long *OPENSSL_ia32cap_loc(void)
296296465Sdelphij{
297296465Sdelphij    return NULL;
298296465Sdelphij}
299160814Ssimon#endif
300160814Ssimonint OPENSSL_NONPIC_relocated = 0;
301160814Ssimon#if !defined(OPENSSL_CPUID_SETUP)
302296465Sdelphijvoid OPENSSL_cpuid_setup(void)
303296465Sdelphij{
304296465Sdelphij}
305160814Ssimon#endif
306160814Ssimon
307160814Ssimon#if (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
308194206Ssimon
309296465Sdelphij# ifdef OPENSSL_FIPS
310194206Ssimon
311296465Sdelphij#  include <tlhelp32.h>
312296465Sdelphij#  if defined(__GNUC__) && __GNUC__>=2
313296465Sdelphijstatic int DllInit(void) __attribute__ ((constructor));
314296465Sdelphij#  elif defined(_MSC_VER)
315194206Ssimonstatic int DllInit(void);
316296465Sdelphij#   ifdef _WIN64
317296465Sdelphij#    pragma section(".CRT$XCU",read)
318296465Sdelphij__declspec(allocate(".CRT$XCU"))
319296465Sdelphij#   else
320296465Sdelphij#    pragma data_seg(".CRT$XCU")
321296465Sdelphij#   endif
322296465Sdelphijstatic int (*p) (void) = DllInit;
323296465Sdelphij#   pragma data_seg()
324296465Sdelphij#  endif
325194206Ssimon
326194206Ssimonstatic int DllInit(void)
327194206Ssimon{
328296465Sdelphij#  if defined(_WIN32_WINNT)
329296465Sdelphij    union {
330296465Sdelphij        int (*f) (void);
331296465Sdelphij        BYTE *p;
332296465Sdelphij    } t = {
333296465Sdelphij        DllInit
334296465Sdelphij    };
335296465Sdelphij    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
336296465Sdelphij    IMAGE_DOS_HEADER *dos_header;
337296465Sdelphij    IMAGE_NT_HEADERS *nt_headers;
338296465Sdelphij    MODULEENTRY32 me32 = { sizeof(me32) };
339194206Ssimon
340296465Sdelphij    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
341296465Sdelphij    if (hModuleSnap != INVALID_HANDLE_VALUE &&
342296465Sdelphij        Module32First(hModuleSnap, &me32))
343296465Sdelphij        do {
344296465Sdelphij            if (t.p >= me32.modBaseAddr &&
345296465Sdelphij                t.p < me32.modBaseAddr + me32.modBaseSize) {
346296465Sdelphij                dos_header = (IMAGE_DOS_HEADER *) me32.modBaseAddr;
347296465Sdelphij                if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
348296465Sdelphij                    nt_headers = (IMAGE_NT_HEADERS *)
349296465Sdelphij                        ((BYTE *) dos_header + dos_header->e_lfanew);
350296465Sdelphij                    if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
351296465Sdelphij                        me32.modBaseAddr !=
352296465Sdelphij                        (BYTE *) nt_headers->OptionalHeader.ImageBase)
353296465Sdelphij                        OPENSSL_NONPIC_relocated = 1;
354296465Sdelphij                }
355296465Sdelphij                break;
356296465Sdelphij            }
357296465Sdelphij        } while (Module32Next(hModuleSnap, &me32));
358194206Ssimon
359296465Sdelphij    if (hModuleSnap != INVALID_HANDLE_VALUE)
360296465Sdelphij        CloseHandle(hModuleSnap);
361296465Sdelphij#  endif
362296465Sdelphij    OPENSSL_cpuid_setup();
363296465Sdelphij    return 0;
364194206Ssimon}
365194206Ssimon
366296465Sdelphij# else
367194206Ssimon
368296465Sdelphij#  ifdef __CYGWIN__
369160814Ssimon/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
370296465Sdelphij#   include <windows.h>
371296465Sdelphij#  endif
372160814Ssimon
373296465Sdelphij/*
374296465Sdelphij * All we really need to do is remove the 'error' state when a thread
375296465Sdelphij * detaches
376296465Sdelphij */
37755714Skris
378296465SdelphijBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
379296465Sdelphij{
380296465Sdelphij    switch (fdwReason) {
381296465Sdelphij    case DLL_PROCESS_ATTACH:
382296465Sdelphij        OPENSSL_cpuid_setup();
383296465Sdelphij#  if defined(_WIN32_WINNT)
384296465Sdelphij        {
385296465Sdelphij            IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *) hinstDLL;
386296465Sdelphij            IMAGE_NT_HEADERS *nt_headers;
387160814Ssimon
388296465Sdelphij            if (dos_header->e_magic == IMAGE_DOS_SIGNATURE) {
389296465Sdelphij                nt_headers = (IMAGE_NT_HEADERS *) ((char *)dos_header
390296465Sdelphij                                                   + dos_header->e_lfanew);
391296465Sdelphij                if (nt_headers->Signature == IMAGE_NT_SIGNATURE &&
392296465Sdelphij                    hinstDLL !=
393296465Sdelphij                    (HINSTANCE) (nt_headers->OptionalHeader.ImageBase))
394296465Sdelphij                    OPENSSL_NONPIC_relocated = 1;
395296465Sdelphij            }
396296465Sdelphij        }
397296465Sdelphij#  endif
398296465Sdelphij        break;
399296465Sdelphij    case DLL_THREAD_ATTACH:
400296465Sdelphij        break;
401296465Sdelphij    case DLL_THREAD_DETACH:
402296465Sdelphij        break;
403296465Sdelphij    case DLL_PROCESS_DETACH:
404296465Sdelphij        break;
405296465Sdelphij    }
406296465Sdelphij    return (TRUE);
407296465Sdelphij}
408296465Sdelphij# endif
40955714Skris
410194206Ssimon#endif
411194206Ssimon
412160814Ssimon#if defined(_WIN32) && !defined(__CYGWIN__)
413296465Sdelphij# include <tchar.h>
414109998Smarkm
415296465Sdelphij# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
416160814Ssimonint OPENSSL_isservice(void)
417296465Sdelphij{
418296465Sdelphij    HWINSTA h;
419296465Sdelphij    DWORD len;
420296465Sdelphij    WCHAR *name;
421142425Snectar
422296465Sdelphij    (void)GetDesktopWindow();   /* return value is ignored */
423142425Snectar
424160814Ssimon    h = GetProcessWindowStation();
425296465Sdelphij    if (h == NULL)
426296465Sdelphij        return -1;
427142425Snectar
428296465Sdelphij    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) ||
429296465Sdelphij        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
430296465Sdelphij        return -1;
431142425Snectar
432296465Sdelphij    if (len > 512)
433296465Sdelphij        return -1;              /* paranoia */
434296465Sdelphij    len++, len &= ~1;           /* paranoia */
435296465Sdelphij#  ifdef _MSC_VER
436296465Sdelphij    name = (WCHAR *)_alloca(len + sizeof(WCHAR));
437296465Sdelphij#  else
438296465Sdelphij    name = (WCHAR *)alloca(len + sizeof(WCHAR));
439296465Sdelphij#  endif
440296465Sdelphij    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
441296465Sdelphij        return -1;
442142425Snectar
443296465Sdelphij    len++, len &= ~1;           /* paranoia */
444296465Sdelphij    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
445296465Sdelphij#  if 1
446296465Sdelphij    /*
447296465Sdelphij     * This doesn't cover "interactive" services [working with real
448296465Sdelphij     * WinSta0's] nor programs started non-interactively by Task Scheduler
449296465Sdelphij     * [those are working with SAWinSta].
450296465Sdelphij     */
451296465Sdelphij    if (wcsstr(name, L"Service-0x"))
452296465Sdelphij        return 1;
453296465Sdelphij#  else
454160814Ssimon    /* This covers all non-interactive programs such as services. */
455296465Sdelphij    if (!wcsstr(name, L"WinSta0"))
456296465Sdelphij        return 1;
457296465Sdelphij#  endif
458296465Sdelphij    else
459296465Sdelphij        return 0;
460160814Ssimon}
461296465Sdelphij# else
462296465Sdelphijint OPENSSL_isservice(void)
463296465Sdelphij{
464296465Sdelphij    return 0;
465296465Sdelphij}
466296465Sdelphij# endif
467142425Snectar
468296465Sdelphijvoid OPENSSL_showfatal(const char *fmta, ...)
469296465Sdelphij{
470296465Sdelphij    va_list ap;
471296465Sdelphij    TCHAR buf[256];
472296465Sdelphij    const TCHAR *fmt;
473296465Sdelphij# ifdef STD_ERROR_HANDLE        /* what a dirty trick! */
474296465Sdelphij    HANDLE h;
475142425Snectar
476296465Sdelphij    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL &&
477296465Sdelphij        GetFileType(h) != FILE_TYPE_UNKNOWN) {
478296465Sdelphij        /* must be console application */
479296465Sdelphij        va_start(ap, fmta);
480296465Sdelphij        vfprintf(stderr, fmta, ap);
481296465Sdelphij        va_end(ap);
482296465Sdelphij        return;
483160814Ssimon    }
484296465Sdelphij# endif
485142425Snectar
486296465Sdelphij    if (sizeof(TCHAR) == sizeof(char))
487296465Sdelphij        fmt = (const TCHAR *)fmta;
488296465Sdelphij    else
489296465Sdelphij        do {
490296465Sdelphij            int keepgoing;
491296465Sdelphij            size_t len_0 = strlen(fmta) + 1, i;
492296465Sdelphij            WCHAR *fmtw;
493142425Snectar
494296465Sdelphij# ifdef _MSC_VER
495296465Sdelphij            fmtw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
496296465Sdelphij# else
497296465Sdelphij            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
498296465Sdelphij# endif
499296465Sdelphij            if (fmtw == NULL) {
500296465Sdelphij                fmt = (const TCHAR *)L"no stack?";
501296465Sdelphij                break;
502296465Sdelphij            }
503296465Sdelphij# ifndef OPENSSL_NO_MULTIBYTE
504296465Sdelphij            if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0))
505296465Sdelphij# endif
506296465Sdelphij                for (i = 0; i < len_0; i++)
507296465Sdelphij                    fmtw[i] = (WCHAR)fmta[i];
508142425Snectar
509296465Sdelphij            for (i = 0; i < len_0; i++) {
510296465Sdelphij                if (fmtw[i] == L'%')
511296465Sdelphij                    do {
512296465Sdelphij                        keepgoing = 0;
513296465Sdelphij                        switch (fmtw[i + 1]) {
514296465Sdelphij                        case L'0':
515296465Sdelphij                        case L'1':
516296465Sdelphij                        case L'2':
517296465Sdelphij                        case L'3':
518296465Sdelphij                        case L'4':
519296465Sdelphij                        case L'5':
520296465Sdelphij                        case L'6':
521296465Sdelphij                        case L'7':
522296465Sdelphij                        case L'8':
523296465Sdelphij                        case L'9':
524296465Sdelphij                        case L'.':
525296465Sdelphij                        case L'*':
526296465Sdelphij                        case L'-':
527296465Sdelphij                            i++;
528296465Sdelphij                            keepgoing = 1;
529296465Sdelphij                            break;
530296465Sdelphij                        case L's':
531296465Sdelphij                            fmtw[i + 1] = L'S';
532296465Sdelphij                            break;
533296465Sdelphij                        case L'S':
534296465Sdelphij                            fmtw[i + 1] = L's';
535296465Sdelphij                            break;
536296465Sdelphij                        case L'c':
537296465Sdelphij                            fmtw[i + 1] = L'C';
538296465Sdelphij                            break;
539296465Sdelphij                        case L'C':
540296465Sdelphij                            fmtw[i + 1] = L'c';
541296465Sdelphij                            break;
542296465Sdelphij                        }
543296465Sdelphij                    } while (keepgoing);
544296465Sdelphij            }
545296465Sdelphij            fmt = (const TCHAR *)fmtw;
546296465Sdelphij        } while (0);
547142425Snectar
548296465Sdelphij    va_start(ap, fmta);
549296465Sdelphij    _vsntprintf(buf, sizeof(buf) / sizeof(TCHAR) - 1, fmt, ap);
550296465Sdelphij    buf[sizeof(buf) / sizeof(TCHAR) - 1] = _T('\0');
551296465Sdelphij    va_end(ap);
552142425Snectar
553296465Sdelphij# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
554160814Ssimon    /* this -------------v--- guards NT-specific calls */
555296465Sdelphij    if (check_winnt() && OPENSSL_isservice() > 0) {
556296465Sdelphij        HANDLE h = RegisterEventSource(0, _T("OPENSSL"));
557296465Sdelphij        const TCHAR *pmsg = buf;
558296465Sdelphij        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 0, 0, 1, 0, &pmsg, 0);
559296465Sdelphij        DeregisterEventSource(h);
560296465Sdelphij    } else
561296465Sdelphij# endif
562296465Sdelphij        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONSTOP);
563160814Ssimon}
564160814Ssimon#else
565296465Sdelphijvoid OPENSSL_showfatal(const char *fmta, ...)
566296465Sdelphij{
567296465Sdelphij    va_list ap;
568142425Snectar
569296465Sdelphij    va_start(ap, fmta);
570296465Sdelphij    vfprintf(stderr, fmta, ap);
571296465Sdelphij    va_end(ap);
572160814Ssimon}
573296465Sdelphij
574296465Sdelphijint OPENSSL_isservice(void)
575296465Sdelphij{
576296465Sdelphij    return 0;
577296465Sdelphij}
578160814Ssimon#endif
579142425Snectar
580296465Sdelphijvoid OpenSSLDie(const char *file, int line, const char *assertion)
581296465Sdelphij{
582296465Sdelphij    OPENSSL_showfatal
583296465Sdelphij        ("%s(%d): OpenSSL internal error, assertion failed: %s\n", file, line,
584296465Sdelphij         assertion);
585296465Sdelphij    abort();
586296465Sdelphij}
587142425Snectar
588296465Sdelphijvoid *OPENSSL_stderr(void)
589296465Sdelphij{
590296465Sdelphij    return stderr;
591296465Sdelphij}
592248272Sdelphij
593248272Sdelphij#ifndef OPENSSL_FIPS
594248272Sdelphij
595248272Sdelphijint CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
596296465Sdelphij{
597296465Sdelphij    size_t i;
598296465Sdelphij    const unsigned char *a = in_a;
599296465Sdelphij    const unsigned char *b = in_b;
600296465Sdelphij    unsigned char x = 0;
601248272Sdelphij
602296465Sdelphij    for (i = 0; i < len; i++)
603296465Sdelphij        x |= a[i] ^ b[i];
604248272Sdelphij
605296465Sdelphij    return x;
606296465Sdelphij}
607248272Sdelphij#endif
608