#endif
DECLARE_STACK_OF(CRYPTO_dynlock)
-IMPLEMENT_STACK_OF(CRYPTO_dynlock)
/* real #defines in crypto.h, keep these upto date */
static const char* const lock_names[CRYPTO_NUM_LOCKS] =
"ec_pre_comp",
"store",
"comp",
-#if CRYPTO_NUM_LOCKS != 39
+ "fips",
+ "fips2",
+#if CRYPTO_NUM_LOCKS != 41
# error "Inconsistency between crypto.h and cryptlib.c"
#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;
+static STACK_OF(OPENSSL_STRING) *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
const char *file,int line)=0;
static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
int type,const char *file,int line)=0;
+#ifndef OPENSSL_NO_DEPRECATED
static unsigned long (MS_FAR *id_callback)(void)=0;
-static void *(MS_FAR *idptr_callback)(void)=0;
+#endif
+static void (MS_FAR *threadid_callback)(CRYPTO_THREADID *)=0;
static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
(const char *file,int line)=0;
static void (MS_FAR *dynlock_lock_callback)(int mode,
#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.
+ * any 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];
#endif
- if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL))
+ if ((app_locks == NULL) && ((app_locks=sk_OPENSSL_STRING_new_null()) == NULL))
{
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
return(0);
CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE);
return(0);
}
- i=sk_push(app_locks,str);
+ i=sk_OPENSSL_STRING_push(app_locks,str);
if (!i)
OPENSSL_free(str);
else
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;
}
add_lock_callback=func;
}
-/* Thread IDs. So ... if we build without OPENSSL_NO_DEPRECATED, then we leave
- * the existing implementations and just layer CRYPTO_THREADID_[get|cmp]
- * harmlessly on top. Otherwise, we only use 'id_callback' or 'idptr_callback'
- * if they're non-NULL, ie. we ignore CRYPTO_thread_id()'s fallbacks and we
- * move CRYPTO_thread_idptr()'s "&errno" fallback trick into
- * CRYPTO_THREADID_set(). */
+/* the memset() here and in set_pointer() seem overkill, but for the sake of
+ * CRYPTO_THREADID_cmp() this avoids any platform silliness that might cause two
+ * "equal" THREADID structs to not be memcmp()-identical. */
+void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
+ {
+ memset(id, 0, sizeof(*id));
+ id->val = val;
+ }
-void CRYPTO_set_id_callback(unsigned long (*func)(void))
+static const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
+void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
{
- id_callback=func;
+ unsigned char *dest = (void *)&id->val;
+ unsigned int accum = 0;
+ unsigned char dnum = sizeof(id->val);
+
+ memset(id, 0, sizeof(*id));
+ id->ptr = ptr;
+ if (sizeof(id->val) >= sizeof(id->ptr))
+ {
+ /* 'ptr' can be embedded in 'val' without loss of uniqueness */
+ id->val = (unsigned long)id->ptr;
+ return;
+ }
+ /* hash ptr ==> val. Each byte of 'val' gets the mod-256 total of a
+ * linear function over the bytes in 'ptr', the co-efficients of which
+ * are a sequence of low-primes (hash_coeffs is an 8-element cycle) -
+ * the starting prime for the sequence varies for each byte of 'val'
+ * (unique polynomials unless pointers are >64-bit). For added spice,
+ * the totals accumulate rather than restarting from zero, and the index
+ * of the 'val' byte is added each time (position dependence). If I was
+ * a black-belt, I'd scan big-endian pointers in reverse to give
+ * low-order bits more play, but this isn't crypto and I'd prefer nobody
+ * mistake it as such. Plus I'm lazy. */
+ while (dnum--)
+ {
+ const unsigned char *src = (void *)&id->ptr;
+ unsigned char snum = sizeof(id->ptr);
+ while (snum--)
+ accum += *(src++) * hash_coeffs[(snum + dnum) & 7];
+ accum += dnum;
+ *(dest++) = accum & 255;
+ }
}
-void CRYPTO_set_idptr_callback(void *(*func)(void))
+int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
{
- idptr_callback=func;
+ if (threadid_callback)
+ return 0;
+ threadid_callback = func;
+ return 1;
}
-void CRYPTO_THREADID_set(CRYPTO_THREADID *id)
+void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *)
{
- memset(id, 0, sizeof(*id));
- if (idptr_callback)
- id->ptr = idptr_callback();
- else if (id_callback)
- id->ulong = id_callback();
- else
- id->ptr = &errno;
+ return threadid_callback;
}
-int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *id1, const CRYPTO_THREADID *id2)
+void CRYPTO_THREADID_current(CRYPTO_THREADID *id)
{
- if (id1->ptr != id2->ptr)
- return ((id1->ptr < id2->ptr) ? -1 : 1);
- if (id1->ulong != id2->ulong)
- return ((id1->ulong < id2->ulong ) ? -1 : 1);
- return 0;
+ if (threadid_callback)
+ {
+ threadid_callback(id);
+ return;
+ }
+#ifndef OPENSSL_NO_DEPRECATED
+ /* If the deprecated callback was set, fall back to that */
+ if (id_callback)
+ {
+ CRYPTO_THREADID_set_numeric(id, id_callback());
+ return;
+ }
+#endif
+ /* Else pick a backup */
+#ifdef OPENSSL_SYS_WIN16
+ CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentTask());
+#elif defined(OPENSSL_SYS_WIN32)
+ CRYPTO_THREADID_set_numeric(id, (unsigned long)GetCurrentThreadId());
+#elif defined(OPENSSL_SYS_BEOS)
+ 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, (void*)&errno);
+#endif
}
-unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
{
- if (idptr_callback || !id_callback)
- return (unsigned long)id->ptr;
- return id->ulong;
+ return memcmp(a, b, sizeof(*a));
}
-void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dst, const CRYPTO_THREADID *src)
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
{
- memcpy(dst, src, sizeof(*src));
+ memcpy(dest, src, sizeof(*src));
+ }
+
+unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
+ {
+ return id->val;
}
#ifndef OPENSSL_NO_DEPRECATED
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;
{
#ifdef LOCK_DEBUG
{
+ CRYPTO_THREADID id;
char *rw_text,*operation_text;
- CRYPTO_THREADID tid;
if (mode & CRYPTO_LOCK)
operation_text="lock ";
else
rw_text="ERROR";
- CRYPTO_THREADID_set(&tid);
+ CRYPTO_THREADID_current(&id);
fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n",
- CRYPTO_THREADID_hash(&tid), rw_text, operation_text,
+ CRYPTO_THREADID_hash(&id), rw_text, operation_text,
CRYPTO_get_lock_name(type), file, line);
}
#endif
int line)
{
int ret = 0;
-#ifdef LOCK_DEBUG
- CRYPTO_THREADID tid;
- CRYPTO_THREADID_set(&tid);
-#endif
if (add_lock_callback != NULL)
{
ret=add_lock_callback(pointer,amount,type,file,line);
#ifdef LOCK_DEBUG
+ {
+ CRYPTO_THREADID id;
+ CRYPTO_THREADID_current(&id);
fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
- CRYPTO_THREADID_hash(&tid), before,amount,ret,
+ CRYPTO_THREADID_hash(&id), before,amount,ret,
CRYPTO_get_lock_name(type),
file,line);
+ }
#endif
}
else
ret= *pointer+amount;
#ifdef LOCK_DEBUG
+ {
+ CRYPTO_THREADID id;
+ CRYPTO_THREADID_current(&id);
fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
- CRYPTO_THREADID_hash(&tid), *pointer,amount,ret,
+ CRYPTO_THREADID_hash(&id),
+ *pointer,amount,ret,
CRYPTO_get_lock_name(type),
file,line);
+ }
#endif
*pointer=ret;
CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line);
return("dynamic");
else if (type < CRYPTO_NUM_LOCKS)
return(lock_names[type]);
- else if (type-CRYPTO_NUM_LOCKS > sk_num(app_locks))
+ else if (type-CRYPTO_NUM_LOCKS > sk_OPENSSL_STRING_num(app_locks))
return("ERROR");
else
- return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS));
+ return(sk_OPENSSL_STRING_value(app_locks,type-CRYPTO_NUM_LOCKS));
}
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__INTEL__) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64)
-
-unsigned long OPENSSL_ia32cap_P=0;
-unsigned long *OPENSSL_ia32cap_loc(void) { return &OPENSSL_ia32cap_P; }
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+
+unsigned int OPENSSL_ia32cap_P[2];
+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;
+ 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(void);
+ 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()&~vec;
+ }
else
- OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid()|(1<<10);
+ vec = OPENSSL_ia32_cpuid();
+
/*
* |(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);
}
#endif
#ifdef __CYGWIN__
/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
#include <windows.h>
+/* this has side-effect of _WIN32 getting defined, which otherwise
+ * is mutually exclusive with __CYGWIN__... */
#endif
/* All we really need to do is remove the 'error' state when a thread
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
- ERR_remove_state(0);
break;
case DLL_PROCESS_DETACH:
break;
#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 */
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;
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
#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);
OPENSSL_showfatal(
"%s(%d): OpenSSL internal error, assertion failed: %s\n",
file,line,assertion);
+#if !defined(_WIN32) || defined(__CYGWIN__)
abort();
+#else
+ /* Win32 abort() customarily shows a dialog, but we just did that... */
+ raise(SIGABRT);
+ _exit(3);
+#endif
}
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;
+ }