X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fcryptlib.c;h=0470597b6eb7ef24f5d7850dd01cc08a83114ce9;hp=009c3be4c0ac4a3546874399ec7b26782964e4a8;hb=8f57662771356882561b98d6add06a16dc479f9b;hpb=c40b9bdefb59be7e640cd7a10bfd2fa26ea1fe7b diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 009c3be4c0..0470597b6e 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -1,578 +1,397 @@ -/* crypto/cryptlib.c */ -/* ==================================================================== - * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. +/* + * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * ECDH support in OpenSSL originally developed by - * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ -#include -#include -#include "cryptlib.h" -#include +#include "e_os.h" +#include "internal/cryptlib_int.h" #include -#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) -static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ -#endif +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) -DECLARE_STACK_OF(CRYPTO_dynlock) -IMPLEMENT_STACK_OF(CRYPTO_dynlock) - -/* real #defines in crypto.h, keep these upto date */ -static const char* lock_names[CRYPTO_NUM_LOCKS] = - { - "<>", - "err", - "ex_data", - "x509", - "x509_info", - "x509_pkey", - "x509_crl", - "x509_req", - "dsa", - "rsa", - "evp_pkey", - "x509_store", - "ssl_ctx", - "ssl_cert", - "ssl_session", - "ssl_sess_cert", - "ssl", - "ssl_method", - "rand", - "rand2", - "debug_malloc", - "BIO", - "gethostbyname", - "getservbyname", - "readdir", - "RSA_blinding", - "dh", - "debug_malloc2", - "dso", - "dynlock", - "engine", - "ui", - "ecdsa", - "ec", - "ecdh", - "bn", - "ec_pre_comp", - "store", - "comp", -#if CRYPTO_NUM_LOCKS != 39 -# error "Inconsistency between crypto.h and cryptlib.c" +extern unsigned int OPENSSL_ia32cap_P[4]; + +# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) +#include +# define OPENSSL_CPUID_SETUP +typedef uint64_t IA32CAP; +void OPENSSL_cpuid_setup(void) +{ + static int trigger = 0; + IA32CAP OPENSSL_ia32_cpuid(unsigned int *); + IA32CAP vec; + char *env; + + if (trigger) + return; + + trigger = 1; + if ((env = getenv("OPENSSL_ia32cap"))) { + int off = (env[0] == '~') ? 1 : 0; +# if defined(_WIN32) + if (!sscanf(env + off, "%I64i", &vec)) + vec = strtoul(env + off, NULL, 0); +# else + if (!sscanf(env + off, "%lli", (long long *)&vec)) + vec = strtoul(env + off, NULL, 0); +# endif + if (off) { + IA32CAP mask = vec; + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask; + if (mask & (1<<24)) { + /* + * User disables FXSR bit, mask even other capabilities + * that operate exclusively on XMM, so we don't have to + * double-check all the time. We mask PCLMULQDQ, AMD XOP, + * AES-NI and AVX. Formally speaking we don't have to + * do it in x86_64 case, but we can safely assume that + * x86_64 users won't actually flip this flag. + */ + vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32); + } + } else if (env[0] == ':') { + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); + } + + if ((env = strchr(env, ':'))) { + IA32CAP vecx; + env++; + off = (env[0] == '~') ? 1 : 0; +# if defined(_WIN32) + if (!sscanf(env + off, "%I64i", &vecx)) + vecx = strtoul(env + off, NULL, 0); +# else + if (!sscanf(env + off, "%lli", (long long *)&vecx)) + vecx = strtoul(env + off, NULL, 0); +# endif + if (off) { + OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; + OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); + } else { + OPENSSL_ia32cap_P[2] = (unsigned int)vecx; + OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); + } + } else { + OPENSSL_ia32cap_P[2] = 0; + OPENSSL_ia32cap_P[3] = 0; + } + } else { + vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); + } + + /* + * |(1<<10) sets a reserved bit to signal that variable + * was initialized already... This is to avoid interference + * with cpuid snippets in ELF .init segment. + */ + OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); + OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); +} +# else +unsigned int OPENSSL_ia32cap_P[4]; +# endif #endif - }; - -/* This is for applications to allocate new type names in the non-dynamic - array of lock names. These are numbered with positive numbers. */ -static STACK *app_locks=NULL; - -/* For applications that want a more dynamic way of handling threads, the - following stack is used. These are externally numbered with negative - numbers. */ -static STACK_OF(CRYPTO_dynlock) *dyn_locks=NULL; - - -static void (MS_FAR *locking_callback)(int mode,int type, - const char *file,int line)=NULL; -static int (MS_FAR *add_lock_callback)(int *pointer,int amount, - int type,const char *file,int line)=NULL; -static unsigned long (MS_FAR *id_callback)(void)=NULL; -static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback) - (const char *file,int line)=NULL; -static void (MS_FAR *dynlock_lock_callback)(int mode, - struct CRYPTO_dynlock_value *l, const char *file,int line)=NULL; -static void (MS_FAR *dynlock_destroy_callback)(struct CRYPTO_dynlock_value *l, - const char *file,int line)=NULL; - -int CRYPTO_get_new_lockid(char *name) - { - char *str; - int i; - -#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) - /* A hack to make Visual C++ 5.0 work correctly when linking as - * a DLL using /MT. Without this, the application cannot use - * and floating point printf's. - * It also seems to be needed for Visual C 1.5 (win16) */ - SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; +int OPENSSL_NONPIC_relocated = 0; +#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) +void OPENSSL_cpuid_setup(void) +{ +} #endif - if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL)) - { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); - return(0); - } - if ((str=BUF_strdup(name)) == NULL) - { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); - return(0); - } - i=sk_push(app_locks,str); - if (!i) - OPENSSL_free(str); - else - i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ - return(i); - } - -int CRYPTO_num_locks(void) - { - return CRYPTO_NUM_LOCKS; - } - -int CRYPTO_get_new_dynlockid(void) - { - int i = 0; - CRYPTO_dynlock *pointer = NULL; - - if (dynlock_create_callback == NULL) - { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK); - return(0); - } - CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); - if ((dyn_locks == NULL) - && ((dyn_locks=sk_CRYPTO_dynlock_new_null()) == NULL)) - { - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); - return(0); - } - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - - pointer = (CRYPTO_dynlock *)OPENSSL_malloc(sizeof(CRYPTO_dynlock)); - if (pointer == NULL) - { - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); - return(0); - } - pointer->references = 1; - pointer->data = dynlock_create_callback(__FILE__,__LINE__); - if (pointer->data == NULL) - { - OPENSSL_free(pointer); - CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID,ERR_R_MALLOC_FAILURE); - return(0); - } - - CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); - /* First, try to find an existing empty slot */ - i=sk_CRYPTO_dynlock_find(dyn_locks,NULL); - /* If there was none, push, thereby creating a new one */ - if (i == -1) - /* Since sk_push() returns the number of items on the - stack, not the location of the pushed item, we need - to transform the returned number into a position, - by decreasing it. */ - i=sk_CRYPTO_dynlock_push(dyn_locks,pointer) - 1; - else - /* If we found a place with a NULL pointer, put our pointer - in it. */ - sk_CRYPTO_dynlock_set(dyn_locks,i,pointer); - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - - if (i == -1) - { - dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); - OPENSSL_free(pointer); - } - else - i += 1; /* to avoid 0 */ - return -i; - } - -void CRYPTO_destroy_dynlockid(int i) - { - CRYPTO_dynlock *pointer = NULL; - if (i) - i = -i-1; - if (dynlock_destroy_callback == NULL) - return; - - CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); - - if (dyn_locks == NULL || i >= sk_CRYPTO_dynlock_num(dyn_locks)) - { - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - return; - } - pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); - if (pointer != NULL) - { - --pointer->references; -#ifdef REF_CHECK - if (pointer->references < 0) - { - fprintf(stderr,"CRYPTO_destroy_dynlockid, bad reference count\n"); - abort(); - } - else -#endif - if (pointer->references <= 0) - { - sk_CRYPTO_dynlock_set(dyn_locks, i, NULL); - } - else - pointer = NULL; - } - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - - if (pointer) - { - dynlock_destroy_callback(pointer->data,__FILE__,__LINE__); - OPENSSL_free(pointer); - } - } - -struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i) - { - CRYPTO_dynlock *pointer = NULL; - if (i) - i = -i-1; - - CRYPTO_w_lock(CRYPTO_LOCK_DYNLOCK); - - if (dyn_locks != NULL && i < sk_CRYPTO_dynlock_num(dyn_locks)) - pointer = sk_CRYPTO_dynlock_value(dyn_locks, i); - if (pointer) - pointer->references++; - - CRYPTO_w_unlock(CRYPTO_LOCK_DYNLOCK); - - if (pointer) - return pointer->data; - return NULL; - } - -struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void)) - (const char *file,int line) - { - return(dynlock_create_callback); - } - -void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, - struct CRYPTO_dynlock_value *l, const char *file,int line) - { - return(dynlock_lock_callback); - } - -void (*CRYPTO_get_dynlock_destroy_callback(void)) - (struct CRYPTO_dynlock_value *l, const char *file,int line) - { - return(dynlock_destroy_callback); - } - -void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*func) - (const char *file, int line)) - { - dynlock_create_callback=func; - } - -void CRYPTO_set_dynlock_lock_callback(void (*func)(int mode, - struct CRYPTO_dynlock_value *l, const char *file, int line)) - { - dynlock_lock_callback=func; - } - -void CRYPTO_set_dynlock_destroy_callback(void (*func) - (struct CRYPTO_dynlock_value *l, const char *file, int line)) - { - dynlock_destroy_callback=func; - } - - -void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, - int line) - { - return(locking_callback); - } - -int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, - const char *file,int line) - { - return(add_lock_callback); - } - -void CRYPTO_set_locking_callback(void (*func)(int mode,int type, - const char *file,int line)) - { - locking_callback=func; - } - -void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, - const char *file,int line)) - { - add_lock_callback=func; - } - -unsigned long (*CRYPTO_get_id_callback(void))(void) - { - return(id_callback); - } - -void CRYPTO_set_id_callback(unsigned long (*func)(void)) - { - id_callback=func; - } - -unsigned long CRYPTO_thread_id(void) - { - unsigned long ret=0; - - if (id_callback == NULL) - { -#ifdef OPENSSL_SYS_WIN16 - ret=(unsigned long)GetCurrentTask(); -#elif defined(OPENSSL_SYS_WIN32) - ret=(unsigned long)GetCurrentThreadId(); -#elif defined(GETPID_IS_MEANINGLESS) - ret=1L; +#if defined(_WIN32) +# include +# include +# ifdef __WATCOMC__ +# if defined(_UNICODE) || defined(__UNICODE__) +# define _vsntprintf _vsnwprintf +# else +# define _vsntprintf _vsnprintf +# endif +# endif +# ifdef _MSC_VER +# define alloca _alloca +# endif + +# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 +# ifdef OPENSSL_SYS_WIN_CORE + +int OPENSSL_isservice(void) +{ + /* OneCore API cannot interact with GUI */ + return 1; +} +# else +int OPENSSL_isservice(void) +{ + HWINSTA h; + DWORD len; + WCHAR *name; + static union { + void *p; + FARPROC f; + } _OPENSSL_isservice = { + NULL + }; + + if (_OPENSSL_isservice.p == NULL) { + HANDLE mod = GetModuleHandle(NULL); + if (mod != NULL) + _OPENSSL_isservice.f = GetProcAddress(mod, "_OPENSSL_isservice"); + if (_OPENSSL_isservice.p == NULL) + _OPENSSL_isservice.p = (void *)-1; + } + + if (_OPENSSL_isservice.p != (void *)-1) + return (*_OPENSSL_isservice.f) (); + + h = GetProcessWindowStation(); + if (h == NULL) + return -1; + + if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return -1; + + if (len > 512) + return -1; /* paranoia */ + len++, len &= ~1; /* paranoia */ + name = (WCHAR *)alloca(len + sizeof(WCHAR)); + if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) + return -1; + + len++, len &= ~1; /* paranoia */ + name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ +# if 1 + /* + * This doesn't cover "interactive" services [working with real + * WinSta0's] nor programs started non-interactively by Task Scheduler + * [those are working with SAWinSta]. + */ + if (wcsstr(name, L"Service-0x")) + return 1; +# else + /* This covers all non-interactive programs such as services. */ + if (!wcsstr(name, L"WinSta0")) + return 1; +# endif + else + return 0; +} +# endif +# else +int OPENSSL_isservice(void) +{ + return 0; +} +# endif + +void OPENSSL_showfatal(const char *fmta, ...) +{ + va_list ap; + TCHAR buf[256]; + const TCHAR *fmt; + /* + * First check if it's a console application, in which case the + * error message would be printed to standard error. + * Windows CE does not have a concept of a console application, + * so we need to guard the check. + */ +# ifdef STD_ERROR_HANDLE + HANDLE h; + + if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && + GetFileType(h) != FILE_TYPE_UNKNOWN) { + /* must be console application */ + int len; + DWORD out; + + va_start(ap, fmta); + len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); + WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); + va_end(ap); + return; + } +# endif + + if (sizeof(TCHAR) == sizeof(char)) + fmt = (const TCHAR *)fmta; + else + do { + int keepgoing; + size_t len_0 = strlen(fmta) + 1, i; + WCHAR *fmtw; + + fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); + if (fmtw == NULL) { + fmt = (const TCHAR *)L"no stack?"; + break; + } + if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) + for (i = 0; i < len_0; i++) + fmtw[i] = (WCHAR)fmta[i]; + for (i = 0; i < len_0; i++) { + if (fmtw[i] == L'%') + do { + keepgoing = 0; + switch (fmtw[i + 1]) { + case L'0': + case L'1': + case L'2': + case L'3': + case L'4': + case L'5': + case L'6': + case L'7': + case L'8': + case L'9': + case L'.': + case L'*': + case L'-': + i++; + keepgoing = 1; + break; + case L's': + fmtw[i + 1] = L'S'; + break; + case L'S': + fmtw[i + 1] = L's'; + break; + case L'c': + fmtw[i + 1] = L'C'; + break; + case L'C': + fmtw[i + 1] = L'c'; + break; + } + } while (keepgoing); + } + fmt = (const TCHAR *)fmtw; + } while (0); + + va_start(ap, fmta); + _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); + buf[OSSL_NELEM(buf) - 1] = _T('\0'); + va_end(ap); + +# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 +# ifdef OPENSSL_SYS_WIN_CORE + /* ONECORE is always NONGUI and NT >= 0x0601 */ + + /* + * TODO: (For non GUI and no std error cases) + * Add event logging feature here. + */ + +# if !defined(NDEBUG) + /* + * We are in a situation where we tried to report a critical + * error and this failed for some reason. As a last resort, + * in debug builds, send output to the debugger or any other + * tool like DebugView which can monitor the output. + */ + OutputDebugString(buf); +# endif +# else + /* this -------------v--- guards NT-specific calls */ + if (check_winnt() && OPENSSL_isservice() > 0) { + HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); + + if (hEventLog != NULL) { + const TCHAR *pmsg = buf; + + if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, + 1, 0, &pmsg, NULL)) { +# if !defined(NDEBUG) + /* + * We are in a situation where we tried to report a critical + * error and this failed for some reason. As a last resort, + * in debug builds, send output to the debugger or any other + * tool like DebugView which can monitor the output. + */ + OutputDebugString(pmsg); +# endif + } + + (void)DeregisterEventSource(hEventLog); + } + } else { + MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); + } +# endif +# else + MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); +# endif +} #else - ret=(unsigned long)getpid(); -#endif - } - else - ret=id_callback(); - return(ret); - } - -void CRYPTO_lock(int mode, int type, const char *file, int line) - { -#ifdef LOCK_DEBUG - { - char *rw_text,*operation_text; - - if (mode & CRYPTO_LOCK) - operation_text="lock "; - else if (mode & CRYPTO_UNLOCK) - operation_text="unlock"; - else - operation_text="ERROR "; - - if (mode & CRYPTO_READ) - rw_text="r"; - else if (mode & CRYPTO_WRITE) - rw_text="w"; - else - rw_text="ERROR"; - - fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", - CRYPTO_thread_id(), rw_text, operation_text, - CRYPTO_get_lock_name(type), file, line); - } -#endif - if (type < 0) - { - if (dynlock_lock_callback != NULL) - { - struct CRYPTO_dynlock_value *pointer - = CRYPTO_get_dynlock_value(type); - - OPENSSL_assert(pointer != NULL); - - dynlock_lock_callback(mode, pointer, file, line); - - CRYPTO_destroy_dynlockid(type); - } - } - else - if (locking_callback != NULL) - locking_callback(mode,type,file,line); - } - -int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, - int line) - { - int ret = 0; - - if (add_lock_callback != NULL) - { -#ifdef LOCK_DEBUG - int before= *pointer; +void OPENSSL_showfatal(const char *fmta, ...) +{ +#ifndef OPENSSL_NO_STDIO + va_list ap; + + va_start(ap, fmta); + vfprintf(stderr, fmta, ap); + va_end(ap); #endif +} - ret=add_lock_callback(pointer,amount,type,file,line); -#ifdef LOCK_DEBUG - fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", - CRYPTO_thread_id(), - before,amount,ret, - CRYPTO_get_lock_name(type), - file,line); -#endif - } - else - { - CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); - - ret= *pointer+amount; -#ifdef LOCK_DEBUG - fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", - CRYPTO_thread_id(), - *pointer,amount,ret, - CRYPTO_get_lock_name(type), - file,line); -#endif - *pointer=ret; - CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); - } - return(ret); - } - -const char *CRYPTO_get_lock_name(int type) - { - if (type < 0) - return("dynamic"); - else if (type < CRYPTO_NUM_LOCKS) - return(lock_names[type]); - else if (type-CRYPTO_NUM_LOCKS > sk_num(app_locks)) - return("ERROR"); - else - return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); - } - -#ifdef _DLL -#ifdef OPENSSL_SYS_WIN32 - -/* All we really need to do is remove the 'error' state when a thread - * detaches */ - -BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, - LPVOID lpvReserved) - { - switch(fdwReason) - { - case DLL_PROCESS_ATTACH: - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - ERR_remove_state(0); - break; - case DLL_PROCESS_DETACH: - break; - } - return(TRUE); - } +int OPENSSL_isservice(void) +{ + return 0; +} #endif +void OPENSSL_die(const char *message, const char *file, int line) +{ + OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", + file, line, message); +#if !defined(_WIN32) + abort(); +#else + /* + * Win32 abort() customarily shows a dialog, but we just did that... + */ +# if !defined(_WIN32_WCE) + raise(SIGABRT); +# endif + _exit(3); +#endif +} + +#if !defined(OPENSSL_CPUID_OBJ) +/* + * The volatile is used to to ensure that the compiler generates code that reads + * all values from the array and doesn't try to optimize this away. The standard + * doesn't actually require this behavior if the original data pointed to is + * not volatile, but compilers do this in practice anyway. + * + * There are also assembler versions of this function. + */ +# undef CRYPTO_memcmp +int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) +{ + size_t i; + const volatile unsigned char *a = in_a; + const volatile unsigned char *b = in_b; + unsigned char x = 0; + + for (i = 0; i < len; i++) + x |= a[i] ^ b[i]; + + return x; +} + +/* + * For systems that don't provide an instruction counter register or equivalent. + */ +uint32_t OPENSSL_rdtsc(void) +{ + return 0; +} #endif - -void OpenSSLDie(const char *file,int line,const char *assertion) - { - fprintf(stderr, - "%s(%d): OpenSSL internal error, assertion failed: %s\n", - file,line,assertion); - abort(); - }