x86_64-xlate.pl: fix jrcxz in nasm case.
[oweals/openssl.git] / crypto / cryptlib.c
index 41be45d620253938421315378bffbe35d6091c06..680dd0a78c95639d2f2606a0837bdbb18e39bb9b 100644 (file)
@@ -409,6 +409,10 @@ int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
 void CRYPTO_set_locking_callback(void (*func)(int mode,int type,
                                              const char *file,int line))
        {
+       /* Calling this here ensures initialisation before any threads
+        * are started.
+        */
+       OPENSSL_init();
        locking_callback=func;
        }
 
@@ -500,7 +504,7 @@ void CRYPTO_THREADID_current(CRYPTO_THREADID *id)
        CRYPTO_THREADID_set_numeric(id, (unsigned long)find_thread(NULL));
 #else
        /* For everything else, default to using the address of 'errno' */
-       CRYPTO_THREADID_set_pointer(id, &errno);
+       CRYPTO_THREADID_set_pointer(id, (void*)&errno);
 #endif
        }
 
@@ -661,29 +665,70 @@ const char *CRYPTO_get_lock_name(int type)
        defined(__INTEL__) || \
        defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
 
-unsigned long  OPENSSL_ia32cap_P=0;
-unsigned long *OPENSSL_ia32cap_loc(void) { return &OPENSSL_ia32cap_P; }
+extern unsigned int  OPENSSL_ia32cap_P[4];
+unsigned long *OPENSSL_ia32cap_loc(void)
+{   if (sizeof(long)==4)
+       /*
+        * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
+        * clear second element to maintain the illusion that vector
+        * is 32-bit.
+        */
+       OPENSSL_ia32cap_P[1]=0;
+
+    OPENSSL_ia32cap_P[2]=0;
+
+    return (unsigned long *)OPENSSL_ia32cap_P;
+}
 
 #if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
 #define OPENSSL_CPUID_SETUP
+#if defined(_WIN32)
+typedef unsigned __int64 IA32CAP;
+#else
+typedef unsigned long long IA32CAP;
+#endif
 void OPENSSL_cpuid_setup(void)
 { static int trigger=0;
-  unsigned long OPENSSL_ia32_cpuid(void);
+  IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
+  IA32CAP vec;
   char *env;
 
     if (trigger)       return;
 
     trigger=1;
-    if ((env=getenv("OPENSSL_ia32cap")))
-       OPENSSL_ia32cap_P = strtoul(env,NULL,0)|(1<<10);
+    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) vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P)&~vec;
+       else if (env[0]==':') vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+
+       OPENSSL_ia32cap_P[2] = 0;
+       if ((env=strchr(env,':'))) {
+           unsigned int vecx;
+           env++;
+           off = (env[0]=='~')?1:0;
+           vecx = strtoul(env+off,NULL,0);
+           if (off)    OPENSSL_ia32cap_P[2] &= ~vecx;
+           else        OPENSSL_ia32cap_P[2] = vecx;
+       }
+    }
     else
-       OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid()|(1<<10);
+       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
 
 #else
@@ -731,7 +776,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
        case DLL_THREAD_ATTACH:
                break;
        case DLL_THREAD_DETACH:
-               ERR_remove_state(0);
                break;
        case DLL_PROCESS_DETACH:
                break;
@@ -743,12 +787,34 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #include <tchar.h>
 #include <signal.h>
+#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
 int OPENSSL_isservice(void)
 { HWINSTA h;
   DWORD len;
   WCHAR *name;
+  static union { void *p; int (*f)(void); } _OPENSSL_isservice = { NULL };
+
+    if (_OPENSSL_isservice.p == NULL) {
+       HANDLE h = GetModuleHandle(NULL);
+       if (h != NULL)
+           _OPENSSL_isservice.p = GetProcAddress(h,"_OPENSSL_isservice");
+       if (_OPENSSL_isservice.p == NULL)
+           _OPENSSL_isservice.p = (void *)-1;
+    }
+
+    if (_OPENSSL_isservice.p != (void *)-1)
+       return (*_OPENSSL_isservice.f)();
 
     (void)GetDesktopWindow(); /* return value is ignored */
 
@@ -761,11 +827,7 @@ int OPENSSL_isservice(void)
 
     if (len>512) return -1;            /* paranoia */
     len++,len&=~1;                     /* paranoia */
-#ifdef _MSC_VER
-    name=(WCHAR *)_alloca(len+sizeof(WCHAR));
-#else
     name=(WCHAR *)alloca(len+sizeof(WCHAR));
-#endif
     if (!GetUserObjectInformationW (h,UOI_NAME,name,len,&len))
        return -1;
 
@@ -810,11 +872,7 @@ void OPENSSL_showfatal (const char *fmta,...)
       size_t len_0=strlen(fmta)+1,i;
       WCHAR *fmtw;
 
-#ifdef _MSC_VER
-       fmtw = (WCHAR *)_alloca (len_0*sizeof(WCHAR));
-#else
-       fmtw = (WCHAR *)alloca (len_0*sizeof(WCHAR));
-#endif
+       fmtw = (WCHAR *)alloca(len_0*sizeof(WCHAR));
        if (fmtw == NULL) { fmt=(const TCHAR *)L"no stack?"; break; }
 
 #ifndef OPENSSL_NO_MULTIBYTE
@@ -847,7 +905,7 @@ void OPENSSL_showfatal (const char *fmta,...)
 
 #if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
     /* this -------------v--- guards NT-specific calls */
-    if (GetVersion() < 0x80000000 && OPENSSL_isservice())
+    if (GetVersion() < 0x80000000 && OPENSSL_isservice() > 0)
     {  HANDLE h = RegisterEventSource(0,_T("OPENSSL"));
        const TCHAR *pmsg=buf;
        ReportEvent(h,EVENTLOG_ERROR_TYPE,0,0,0,1,0,&pmsg,0);
@@ -883,3 +941,16 @@ void OpenSSLDie(const char *file,int line,const char *assertion)
        }
 
 void *OPENSSL_stderr(void)     { return stderr; }
+
+int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
+       {
+       size_t i;
+       const unsigned char *a = in_a;
+       const unsigned char *b = in_b;
+       unsigned char x = 0;
+
+       for (i = 0; i < len; i++)
+               x |= a[i] ^ b[i];
+
+       return x;
+       }