提交 4c329696 编写于 作者: G Geoff Thorpe

Remove the dual-callback scheme for numeric and pointer thread IDs,

deprecate the original (numeric-only) scheme, and replace with the
CRYPTO_THREADID object. This hides the platform-specifics and should reduce
the possibility for programming errors (where failing to explicitly check
both thread ID forms could create subtle, platform-specific bugs).

Thanks to Bodo, for invaluable review and feedback.
上级 96826bfc
...@@ -4,6 +4,30 @@ ...@@ -4,6 +4,30 @@
Changes between 0.9.8i and 0.9.9 [xx XXX xxxx] Changes between 0.9.8i and 0.9.9 [xx XXX xxxx]
*) To cater for systems that provide a pointer-based thread ID rather
than numeric, deprecate the current numeric thread ID mechanism and
replace it with a structure and associated callback type. This
mechanism allows a numeric "hash" to be extracted from a thread ID in
either case, and on platforms where pointers are larger than 'long',
mixing is done to help ensure the numeric 'hash' is usable even if it
can't be guaranteed unique. The default mechanism is to use "&errno"
as a pointer-based thread ID to distinguish between threads.
Applications that want to provide their own thread IDs should now use
CRYPTO_THREADID_set_callback() to register a callback that will call
either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer().
(This new approach replaces the functions CRYPTO_set_idptr_callback(),
CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in
OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an
application was previously providing a numeric thread callback that
was inappropriate for distinguishing threads, then uniqueness might
have been obtained with &errno that happened immediately in the
intermediate development versions of OpenSSL; this is no longer the
case, the numeric thread callback will now override the automatic use
of &errno.)
[Geoff Thorpe, with help from Bodo Moeller]
*) Initial support for different CRL issuing certificates. This covers a *) Initial support for different CRL issuing certificates. This covers a
simple case where the self issued certificates in the chain exist and simple case where the self issued certificates in the chain exist and
the real CRL issuer is higher in the existing chain. the real CRL issuer is higher in the existing chain.
...@@ -307,30 +331,6 @@ ...@@ -307,30 +331,6 @@
list-message-digest-algorithms and list-cipher-algorithms. list-message-digest-algorithms and list-cipher-algorithms.
[Steve Henson] [Steve Henson]
*) In addition to the numerical (unsigned long) thread ID, provide
for a pointer (void *) thread ID. This helps accomodate systems
that do not provide an unsigned long thread ID. OpenSSL assumes
it is in the same thread iff both the numerical and the pointer
thread ID agree; so applications are just required to define one
of them appropriately (e.g., by using a pointer to a per-thread
memory object malloc()ed by the application for the pointer-type
thread ID). Exactly analoguous to the existing functions
void CRYPTO_set_id_callback(unsigned long (*func)(void));
unsigned long (*CRYPTO_get_id_callback(void))(void);
unsigned long CRYPTO_thread_id(void);
we now have additional functions
void CRYPTO_set_idptr_callback(void *(*func)(void));
void *(*CRYPTO_get_idptr_callback(void))(void);
void *CRYPTO_thread_idptr(void);
also in <openssl/crypto.h>. The default value for
CRYPTO_thread_idptr() if the application has not provided its own
callback is &errno.
[Bodo Moeller]
*) Change the array representation of binary polynomials: the list *) Change the array representation of binary polynomials: the list
of degrees of non-zero coefficients is now terminated with -1. of degrees of non-zero coefficients is now terminated with -1.
Previously it was terminated with 0, which was also part of the Previously it was terminated with 0, which was also part of the
......
...@@ -717,9 +717,7 @@ file. ...@@ -717,9 +717,7 @@ file.
Multi-threaded applications must provide two callback functions to Multi-threaded applications must provide two callback functions to
OpenSSL by calling CRYPTO_set_locking_callback() and OpenSSL by calling CRYPTO_set_locking_callback() and
CRYPTO_set_id_callback(). (For OpenSSL 0.9.9 or later, the new CRYPTO_set_id_callback(). This is described in the threads(3)
function CRYPTO_set_idptr_callback() may be used in place of
CRYPTO_set_id_callback().) This is described in the threads(3)
manpage. manpage.
* I've compiled a program under Windows and it crashes: why? * I've compiled a program under Windows and it crashes: why?
......
...@@ -181,7 +181,7 @@ extern BIO *bio_err; ...@@ -181,7 +181,7 @@ extern BIO *bio_err;
# define apps_shutdown() \ # define apps_shutdown() \
do { CONF_modules_unload(1); destroy_ui_method(); \ do { CONF_modules_unload(1); destroy_ui_method(); \
OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \ OBJ_cleanup(); EVP_cleanup(); ENGINE_cleanup(); \
CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); \ CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \
ERR_free_strings(); COMP_zlib_cleanup();} while(0) ERR_free_strings(); COMP_zlib_cleanup();} while(0)
# else # else
# define apps_startup() \ # define apps_startup() \
...@@ -191,7 +191,7 @@ extern BIO *bio_err; ...@@ -191,7 +191,7 @@ extern BIO *bio_err;
# define apps_shutdown() \ # define apps_shutdown() \
do { CONF_modules_unload(1); destroy_ui_method(); \ do { CONF_modules_unload(1); destroy_ui_method(); \
OBJ_cleanup(); EVP_cleanup(); \ OBJ_cleanup(); EVP_cleanup(); \
CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); \ CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); \
ERR_free_strings(); } while(0) ERR_free_strings(); } while(0)
# endif # endif
#endif #endif
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
#include <stdio.h> /* FILE */ #include <stdio.h> /* FILE */
#endif #endif
#include <openssl/ossl_typ.h> #include <openssl/ossl_typ.h>
#include <openssl/crypto.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -564,10 +565,11 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); ...@@ -564,10 +565,11 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *); int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *); int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
#ifndef OPENSSL_NO_DEPRECATED
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *); unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long); void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
void *BN_BLINDING_get_thread_idptr(const BN_BLINDING *); #endif
void BN_BLINDING_set_thread_idptr(BN_BLINDING *, void *); CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
......
...@@ -121,10 +121,11 @@ struct bn_blinding_st ...@@ -121,10 +121,11 @@ struct bn_blinding_st
BIGNUM *Ai; BIGNUM *Ai;
BIGNUM *e; BIGNUM *e;
BIGNUM *mod; /* just a reference */ BIGNUM *mod; /* just a reference */
#ifndef OPENSSL_NO_DEPRECATED
unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b; unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b;
* used only by crypto/rsa/rsa_eay.c, rsa_lib.c */ * used only by crypto/rsa/rsa_eay.c, rsa_lib.c */
void *thread_idptr; /* added in OpenSSL 0.9.9; #endif
* used only by crypto/rsa/rsa_eay.c, rsa_lib.c */ CRYPTO_THREADID tid;
unsigned int counter; unsigned int counter;
unsigned long flags; unsigned long flags;
BN_MONT_CTX *m_ctx; BN_MONT_CTX *m_ctx;
...@@ -160,6 +161,7 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) ...@@ -160,6 +161,7 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
BN_set_flags(ret->mod, BN_FLG_CONSTTIME); BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
ret->counter = BN_BLINDING_COUNTER; ret->counter = BN_BLINDING_COUNTER;
CRYPTO_THREADID_current(&ret->tid);
return(ret); return(ret);
err: err:
if (ret != NULL) BN_BLINDING_free(ret); if (ret != NULL) BN_BLINDING_free(ret);
...@@ -265,6 +267,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ct ...@@ -265,6 +267,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ct
return(ret); return(ret);
} }
#ifndef OPENSSL_NO_DEPRECATED
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b) unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b)
{ {
return b->thread_id; return b->thread_id;
...@@ -274,15 +277,11 @@ void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long n) ...@@ -274,15 +277,11 @@ void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long n)
{ {
b->thread_id = n; b->thread_id = n;
} }
#endif
void *BN_BLINDING_get_thread_idptr(const BN_BLINDING *b) CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *b)
{ {
return b->thread_idptr; return &b->tid;
}
void BN_BLINDING_set_thread_idptr(BN_BLINDING *b, void *p)
{
b->thread_idptr = p;
} }
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
......
...@@ -187,7 +187,7 @@ int main(int argc, char *argv[]) ...@@ -187,7 +187,7 @@ int main(int argc, char *argv[])
BN_free(b); BN_free(b);
BN_free(m); BN_free(m);
BN_CTX_free(ctx); BN_CTX_free(ctx);
ERR_remove_state(0); ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks(out); CRYPTO_mem_leaks(out);
BIO_free(out); BIO_free(out);
printf(" done\n"); printf(" done\n");
......
...@@ -184,8 +184,10 @@ static void (MS_FAR *locking_callback)(int mode,int type, ...@@ -184,8 +184,10 @@ static void (MS_FAR *locking_callback)(int mode,int type,
const char *file,int line)=0; const char *file,int line)=0;
static int (MS_FAR *add_lock_callback)(int *pointer,int amount, static int (MS_FAR *add_lock_callback)(int *pointer,int amount,
int type,const char *file,int line)=0; int type,const char *file,int line)=0;
#ifndef OPENSSL_NO_DEPRECATED
static unsigned long (MS_FAR *id_callback)(void)=0; 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) static struct CRYPTO_dynlock_value *(MS_FAR *dynlock_create_callback)
(const char *file,int line)=0; (const char *file,int line)=0;
static void (MS_FAR *dynlock_lock_callback)(int mode, static void (MS_FAR *dynlock_lock_callback)(int mode,
...@@ -414,6 +416,108 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, ...@@ -414,6 +416,108 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
add_lock_callback=func; add_lock_callback=func;
} }
/* 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;
}
static const unsigned char hash_coeffs[] = { 3, 5, 7, 11, 13, 17, 19, 23 };
void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
{
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;
}
}
int CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
{
if (threadid_callback)
return 0;
threadid_callback = func;
return 1;
}
void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *)
{
return threadid_callback;
}
void CRYPTO_THREADID_current(CRYPTO_THREADID *id)
{
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, &errno);
#endif
}
int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
{
return memcmp(a, b, sizeof(*a));
}
void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
{
memcpy(dest, src, sizeof(*src));
}
unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
{
return id->val;
}
#ifndef OPENSSL_NO_DEPRECATED
unsigned long (*CRYPTO_get_id_callback(void))(void) unsigned long (*CRYPTO_get_id_callback(void))(void)
{ {
return(id_callback); return(id_callback);
...@@ -446,33 +550,13 @@ unsigned long CRYPTO_thread_id(void) ...@@ -446,33 +550,13 @@ unsigned long CRYPTO_thread_id(void)
ret=id_callback(); ret=id_callback();
return(ret); return(ret);
} }
#endif
void *(*CRYPTO_get_idptr_callback(void))(void)
{
return(idptr_callback);
}
void CRYPTO_set_idptr_callback(void *(*func)(void))
{
idptr_callback=func;
}
void *CRYPTO_thread_idptr(void)
{
void *ret=NULL;
if (idptr_callback == NULL)
ret = &errno;
else
ret = idptr_callback();
return ret;
}
void CRYPTO_lock(int mode, int type, const char *file, int line) void CRYPTO_lock(int mode, int type, const char *file, int line)
{ {
#ifdef LOCK_DEBUG #ifdef LOCK_DEBUG
{ {
CRYPTO_THREADID id;
char *rw_text,*operation_text; char *rw_text,*operation_text;
if (mode & CRYPTO_LOCK) if (mode & CRYPTO_LOCK)
...@@ -489,8 +573,9 @@ void CRYPTO_lock(int mode, int type, const char *file, int line) ...@@ -489,8 +573,9 @@ void CRYPTO_lock(int mode, int type, const char *file, int line)
else else
rw_text="ERROR"; rw_text="ERROR";
fprintf(stderr,"lock:%08lx/%08p:(%s)%s %-18s %s:%d\n", CRYPTO_THREADID_current(&id);
CRYPTO_thread_id(), CRYPTO_thread_idptr(), rw_text, operation_text, fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n",
CRYPTO_THREADID_hash(&id), rw_text, operation_text,
CRYPTO_get_lock_name(type), file, line); CRYPTO_get_lock_name(type), file, line);
} }
#endif #endif
...@@ -526,11 +611,14 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, ...@@ -526,11 +611,14 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
ret=add_lock_callback(pointer,amount,type,file,line); ret=add_lock_callback(pointer,amount,type,file,line);
#ifdef LOCK_DEBUG #ifdef LOCK_DEBUG
fprintf(stderr,"ladd:%08lx/%0xp:%2d+%2d->%2d %-18s %s:%d\n", {
CRYPTO_thread_id(), CRYPTO_thread_idptr(), CRYPTO_THREADID id;
before,amount,ret, CRYPTO_THREADID_current(&id);
fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
CRYPTO_THREADID_hash(&id), before,amount,ret,
CRYPTO_get_lock_name(type), CRYPTO_get_lock_name(type),
file,line); file,line);
}
#endif #endif
} }
else else
...@@ -539,11 +627,15 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, ...@@ -539,11 +627,15 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
ret= *pointer+amount; ret= *pointer+amount;
#ifdef LOCK_DEBUG #ifdef LOCK_DEBUG
fprintf(stderr,"ladd:%08lx/%0xp:%2d+%2d->%2d %-18s %s:%d\n", {
CRYPTO_thread_id(), CRYPTO_thread_idptr(), CRYPTO_THREADID id;
CRYPTO_THREADID_current(&id);
fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
CRYPTO_THREADID_hash(&id),
*pointer,amount,ret, *pointer,amount,ret,
CRYPTO_get_lock_name(type), CRYPTO_get_lock_name(type),
file,line); file,line);
}
#endif #endif
*pointer=ret; *pointer=ret;
CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line);
......
...@@ -421,12 +421,27 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, ...@@ -421,12 +421,27 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
const char *file, int line)); const char *file, int line));
int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
const char *file,int line); const char *file,int line);
/* Don't use this structure directly. */
typedef struct crypto_threadid_st
{
void *ptr;
unsigned long val;
} CRYPTO_THREADID;
/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val);
void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID *));
void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *);
void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b);
void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src);
unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
#ifndef OPENSSL_NO_DEPRECATED
void CRYPTO_set_id_callback(unsigned long (*func)(void)); void CRYPTO_set_id_callback(unsigned long (*func)(void));
unsigned long (*CRYPTO_get_id_callback(void))(void); unsigned long (*CRYPTO_get_id_callback(void))(void);
unsigned long CRYPTO_thread_id(void); unsigned long CRYPTO_thread_id(void);
void CRYPTO_set_idptr_callback(void *(*func)(void)); #endif
void *(*CRYPTO_get_idptr_callback(void))(void);
void *CRYPTO_thread_idptr(void);
const char *CRYPTO_get_lock_name(int type); const char *CRYPTO_get_lock_name(int type);
int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file, int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
......
...@@ -222,7 +222,7 @@ end: ...@@ -222,7 +222,7 @@ end:
ERR_print_errors(bio_err); ERR_print_errors(bio_err);
if (dsa != NULL) DSA_free(dsa); if (dsa != NULL) DSA_free(dsa);
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
ERR_free_strings(); ERR_free_strings();
CRYPTO_mem_leaks(bio_err); CRYPTO_mem_leaks(bio_err);
if (bio_err != NULL) if (bio_err != NULL)
......
...@@ -1326,7 +1326,7 @@ int main(int argc, char *argv[]) ...@@ -1326,7 +1326,7 @@ int main(int argc, char *argv[])
#endif #endif
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_free_strings(); ERR_free_strings();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks_fp(stderr); CRYPTO_mem_leaks_fp(stderr);
return 0; return 0;
......
...@@ -343,7 +343,7 @@ err: ...@@ -343,7 +343,7 @@ err:
if (ctx) BN_CTX_free(ctx); if (ctx) BN_CTX_free(ctx);
BIO_free(out); BIO_free(out);
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks_fp(stderr); CRYPTO_mem_leaks_fp(stderr);
EXIT(ret); EXIT(ret);
return(ret); return(ret);
......
...@@ -490,7 +490,7 @@ err: ...@@ -490,7 +490,7 @@ err:
if (ret) if (ret)
ERR_print_errors(out); ERR_print_errors(out);
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
ERR_free_strings(); ERR_free_strings();
CRYPTO_mem_leaks(out); CRYPTO_mem_leaks(out);
if (out != NULL) if (out != NULL)
......
...@@ -276,7 +276,7 @@ end: ...@@ -276,7 +276,7 @@ end:
ENGINE_cleanup(); ENGINE_cleanup();
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_free_strings(); ERR_free_strings();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks_fp(stderr); CRYPTO_mem_leaks_fp(stderr);
return to_return; return to_return;
} }
......
...@@ -429,13 +429,13 @@ static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) ...@@ -429,13 +429,13 @@ static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
static unsigned long err_state_hash(const ERR_STATE *a) static unsigned long err_state_hash(const ERR_STATE *a)
{ {
return (a->pid + (unsigned long)a->pidptr) * 13; return CRYPTO_THREADID_hash(&a->tid) * 13;
} }
static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE) static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
{ {
return (a->pid != b->pid) || (a->pidptr != b->pidptr); return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
} }
static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE) static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
...@@ -980,40 +980,37 @@ const char *ERR_reason_error_string(unsigned long e) ...@@ -980,40 +980,37 @@ const char *ERR_reason_error_string(unsigned long e)
return((p == NULL)?NULL:p->string); return((p == NULL)?NULL:p->string);
} }
void ERR_remove_state(unsigned long pid) void ERR_remove_thread_state(const CRYPTO_THREADID *id)
{ {
ERR_STATE tmp; ERR_STATE tmp;
void *pidptr;
err_fns_check(); if (id)
if (pid != 0) CRYPTO_THREADID_cpy(&tmp.tid, id);
pidptr = &errno;
else else
{ CRYPTO_THREADID_current(&tmp.tid);
pid = CRYPTO_thread_id(); err_fns_check();
pidptr = CRYPTO_thread_idptr();
}
tmp.pid=pid;
tmp.pidptr=pidptr;
/* thread_del_item automatically destroys the LHASH if the number of /* thread_del_item automatically destroys the LHASH if the number of
* items reaches zero. */ * items reaches zero. */
ERRFN(thread_del_item)(&tmp); ERRFN(thread_del_item)(&tmp);
} }
#ifndef OPENSSL_NO_DEPRECATED
void ERR_remove_state(unsigned long pid)
{
ERR_remove_thread_state(NULL);
}
#endif
ERR_STATE *ERR_get_state(void) ERR_STATE *ERR_get_state(void)
{ {
static ERR_STATE fallback; static ERR_STATE fallback;
ERR_STATE *ret,tmp,*tmpp=NULL; ERR_STATE *ret,tmp,*tmpp=NULL;
int i; int i;
unsigned long pid; CRYPTO_THREADID tid;
void *pidptr;
err_fns_check(); err_fns_check();
pid = CRYPTO_thread_id(); CRYPTO_THREADID_current(&tid);
pidptr = CRYPTO_thread_idptr(); CRYPTO_THREADID_cpy(&tmp.tid, &tid);
tmp.pid = pid;
tmp.pidptr = pidptr;
ret=ERRFN(thread_get_item)(&tmp); ret=ERRFN(thread_get_item)(&tmp);
/* ret == the error state, if NULL, make a new one */ /* ret == the error state, if NULL, make a new one */
...@@ -1021,8 +1018,7 @@ ERR_STATE *ERR_get_state(void) ...@@ -1021,8 +1018,7 @@ ERR_STATE *ERR_get_state(void)
{ {
ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
if (ret == NULL) return(&fallback); if (ret == NULL) return(&fallback);
ret->pid=pid; CRYPTO_THREADID_cpy(&ret->tid, &tid);
ret->pidptr=pidptr;
ret->top=0; ret->top=0;
ret->bottom=0; ret->bottom=0;
for (i=0; i<ERR_NUM_ERRORS; i++) for (i=0; i<ERR_NUM_ERRORS; i++)
......
...@@ -147,8 +147,7 @@ extern "C" { ...@@ -147,8 +147,7 @@ extern "C" {
#define ERR_NUM_ERRORS 16 #define ERR_NUM_ERRORS 16
typedef struct err_state_st typedef struct err_state_st
{ {
unsigned long pid; CRYPTO_THREADID tid;
void *pidptr; /* new in OpenSSL 0.9.9 */
int err_flags[ERR_NUM_ERRORS]; int err_flags[ERR_NUM_ERRORS];
unsigned long err_buffer[ERR_NUM_ERRORS]; unsigned long err_buffer[ERR_NUM_ERRORS];
char *err_data[ERR_NUM_ERRORS]; char *err_data[ERR_NUM_ERRORS];
...@@ -351,7 +350,10 @@ void ERR_load_ERR_strings(void); ...@@ -351,7 +350,10 @@ void ERR_load_ERR_strings(void);
void ERR_load_crypto_strings(void); void ERR_load_crypto_strings(void);
void ERR_free_strings(void); void ERR_free_strings(void);
void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
#ifndef OPENSSL_NO_DEPRECATED
void ERR_remove_state(unsigned long pid); /* if zero we look it up */ void ERR_remove_state(unsigned long pid); /* if zero we look it up */
#endif
ERR_STATE *ERR_get_state(void); ERR_STATE *ERR_get_state(void);
#ifndef OPENSSL_NO_LHASH #ifndef OPENSSL_NO_LHASH
......
...@@ -72,8 +72,10 @@ void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), ...@@ -72,8 +72,10 @@ void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
const char *file,*data; const char *file,*data;
int line,flags; int line,flags;
unsigned long es; unsigned long es;
CRYPTO_THREADID cur;
es=CRYPTO_thread_id(); CRYPTO_THREADID_current(&cur);
es=CRYPTO_THREADID_hash(&cur);
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
{ {
ERR_error_string_n(l, buf, sizeof buf); ERR_error_string_n(l, buf, sizeof buf);
......
...@@ -441,7 +441,7 @@ int main(int argc,char **argv) ...@@ -441,7 +441,7 @@ int main(int argc,char **argv)
#endif #endif
EVP_cleanup(); EVP_cleanup();
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
ERR_free_strings(); ERR_free_strings();
CRYPTO_mem_leaks_fp(stderr); CRYPTO_mem_leaks_fp(stderr);
......
...@@ -150,8 +150,7 @@ typedef struct app_mem_info_st ...@@ -150,8 +150,7 @@ typedef struct app_mem_info_st
* CRYPTO_remove_all_info() to pop all entries. * CRYPTO_remove_all_info() to pop all entries.
*/ */
{ {
unsigned long thread_id; CRYPTO_THREADID threadid;
void *thread_idptr;
const char *file; const char *file;
int line; int line;
const char *info; const char *info;
...@@ -176,8 +175,7 @@ typedef struct mem_st ...@@ -176,8 +175,7 @@ typedef struct mem_st
int num; int num;
const char *file; const char *file;
int line; int line;
unsigned long thread_id; CRYPTO_THREADID threadid;
void *thread_idptr;
unsigned long order; unsigned long order;
time_t time; time_t time;
APP_INFO *app_info; APP_INFO *app_info;
...@@ -198,12 +196,10 @@ static unsigned int num_disable = 0; /* num_disable > 0 ...@@ -198,12 +196,10 @@ static unsigned int num_disable = 0; /* num_disable > 0
* mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
*/ */
/* The following two variables, disabling_thread_id and disabling_thread_idptr, /* Valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in this
* are valid iff num_disable > 0. CRYPTO_LOCK_MALLOC2 is locked exactly in * case (by the thread named in disabling_thread).
* this case (by the thread named in disabling_thread_id / disabling_thread_idptr).
*/ */
static unsigned long disabling_thread_id = 0; static CRYPTO_THREADID disabling_threadid;
static void *disabling_thread_idptr = NULL;
static void app_info_free(APP_INFO *inf) static void app_info_free(APP_INFO *inf)
{ {
...@@ -240,9 +236,9 @@ int CRYPTO_mem_ctrl(int mode) ...@@ -240,9 +236,9 @@ int CRYPTO_mem_ctrl(int mode)
case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */ case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
if (mh_mode & CRYPTO_MEM_CHECK_ON) if (mh_mode & CRYPTO_MEM_CHECK_ON)
{ {
if (!num_disable CRYPTO_THREADID cur;
|| (disabling_thread_id != CRYPTO_thread_id()) CRYPTO_THREADID_current(&cur);
|| (disabling_thread_idptr != CRYPTO_thread_idptr())) /* otherwise we already have the MALLOC2 lock */ if (!num_disable || CRYPTO_THREADID_cmp(&disabling_threadid, &cur)) /* otherwise we already have the MALLOC2 lock */
{ {
/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
* we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
...@@ -260,8 +256,7 @@ int CRYPTO_mem_ctrl(int mode) ...@@ -260,8 +256,7 @@ int CRYPTO_mem_ctrl(int mode)
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2); CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC); CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE; mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
disabling_thread_id=CRYPTO_thread_id(); CRYPTO_THREADID_cpy(&disabling_threadid, &cur);
disabling_thread_idptr=CRYPTO_thread_idptr();
} }
num_disable++; num_disable++;
} }
...@@ -294,11 +289,12 @@ int CRYPTO_is_mem_check_on(void) ...@@ -294,11 +289,12 @@ int CRYPTO_is_mem_check_on(void)
if (mh_mode & CRYPTO_MEM_CHECK_ON) if (mh_mode & CRYPTO_MEM_CHECK_ON)
{ {
CRYPTO_THREADID cur;
CRYPTO_THREADID_current(&cur);
CRYPTO_r_lock(CRYPTO_LOCK_MALLOC); CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
|| (disabling_thread_id != CRYPTO_thread_id()) || CRYPTO_THREADID_cmp(&disabling_threadid, &cur);
|| (disabling_thread_idptr != CRYPTO_thread_idptr());
CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC); CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
} }
...@@ -344,20 +340,17 @@ static IMPLEMENT_LHASH_HASH_FN(mem, MEM) ...@@ -344,20 +340,17 @@ static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */ /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
static int app_info_cmp(const void *a_void, const void *b_void) static int app_info_cmp(const void *a_void, const void *b_void)
{ {
return (((const APP_INFO *)a_void)->thread_id != ((const APP_INFO *)b_void)->thread_id) return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
|| (((const APP_INFO *)a_void)->thread_idptr != ((const APP_INFO *)b_void)->thread_idptr); &((const APP_INFO *)b_void)->threadid);
} }
static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO) static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
static unsigned long app_info_hash(const APP_INFO *a) static unsigned long app_info_hash(const APP_INFO *a)
{ {
unsigned long id1, id2;
unsigned long ret; unsigned long ret;
id1=(unsigned long)a->thread_id; ret = CRYPTO_THREADID_hash(&a->threadid);
id2=(unsigned long)a->thread_idptr; /* This is left in as a "who am I to question legacy?" measure */
ret = id1 + id2;
ret=ret*17851+(ret>>14)*7+(ret>>4)*251; ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
return(ret); return(ret);
} }
...@@ -370,8 +363,7 @@ static APP_INFO *pop_info(void) ...@@ -370,8 +363,7 @@ static APP_INFO *pop_info(void)
if (amih != NULL) if (amih != NULL)
{ {
tmp.thread_id=CRYPTO_thread_id(); CRYPTO_THREADID_current(&tmp.threadid);
tmp.thread_idptr=CRYPTO_thread_idptr();
if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL) if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL)
{ {
APP_INFO *next=ret->next; APP_INFO *next=ret->next;
...@@ -382,10 +374,11 @@ static APP_INFO *pop_info(void) ...@@ -382,10 +374,11 @@ static APP_INFO *pop_info(void)
(void)lh_APP_INFO_insert(amih,next); (void)lh_APP_INFO_insert(amih,next);
} }
#ifdef LEVITTE_DEBUG_MEM #ifdef LEVITTE_DEBUG_MEM
if (ret->thread_id != tmp.thread_id || ret->thread_idptr != tmp.thread_idptr) if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid))
{ {
fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu/%p) than the current thread (%lu/%p)!!!!\n", fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
ret->thread_id, ret->thread_idptr, tmp.thread_id, tmp.thread_idptr); CRYPTO_THREADID_hash(&ret->threadid),
CRYPTO_THREADID_hash(&tmp.threadid));
abort(); abort();
} }
#endif #endif
...@@ -425,8 +418,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) ...@@ -425,8 +418,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
} }
} }
ami->thread_id=CRYPTO_thread_id(); CRYPTO_THREADID_current(&ami->threadid);
ami->thread_idptr=CRYPTO_thread_idptr();
ami->file=file; ami->file=file;
ami->line=line; ami->line=line;
ami->info=info; ami->info=info;
...@@ -436,10 +428,11 @@ int CRYPTO_push_info_(const char *info, const char *file, int line) ...@@ -436,10 +428,11 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL) if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL)
{ {
#ifdef LEVITTE_DEBUG_MEM #ifdef LEVITTE_DEBUG_MEM
if (ami->thread_id != amim->thread_id || ami->thread_idptr != amim->thread_idptr) if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid))
{ {
fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu/%p) than the current thread (%lu/%p)!!!!\n", fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
amim->thread_id, amim->thread_idptr, ami->thread_id, ami->thread_idptr); CRYPTO_THREADID_hash(&amim->threadid),
CRYPTO_THREADID_hash(&ami->threadid));
abort(); abort();
} }
#endif #endif
...@@ -525,15 +518,9 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, ...@@ -525,15 +518,9 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
m->line=line; m->line=line;
m->num=num; m->num=num;
if (options & V_CRYPTO_MDEBUG_THREAD) if (options & V_CRYPTO_MDEBUG_THREAD)
{ CRYPTO_THREADID_current(&m->threadid);
m->thread_id=CRYPTO_thread_id();
m->thread_idptr=CRYPTO_thread_idptr();
}
else else
{ memset(&m->threadid, 0, sizeof(m->threadid));
m->thread_id=0;
m->thread_idptr=NULL;
}
if (order == break_order_num) if (order == break_order_num)
{ {
...@@ -552,8 +539,7 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, ...@@ -552,8 +539,7 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
else else
m->time=0; m->time=0;
tmp.thread_id=CRYPTO_thread_id(); CRYPTO_THREADID_current(&tmp.threadid);
tmp.thread_idptr=CRYPTO_thread_idptr();
m->app_info=NULL; m->app_info=NULL;
if (amih != NULL if (amih != NULL
&& (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL) && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL)
...@@ -682,8 +668,7 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) ...@@ -682,8 +668,7 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
APP_INFO *amip; APP_INFO *amip;
int ami_cnt; int ami_cnt;
struct tm *lcl = NULL; struct tm *lcl = NULL;
unsigned long ti; CRYPTO_THREADID ti;
void *tip;
#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf)) #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
...@@ -705,7 +690,8 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) ...@@ -705,7 +690,8 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
if (options & V_CRYPTO_MDEBUG_THREAD) if (options & V_CRYPTO_MDEBUG_THREAD)
{ {
BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu/%p, ", m->thread_id, m->thread_idptr); BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
CRYPTO_THREADID_hash(&m->threadid));
bufp += strlen(bufp); bufp += strlen(bufp);
} }
...@@ -722,9 +708,8 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) ...@@ -722,9 +708,8 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
ami_cnt=0; ami_cnt=0;
if (!amip) if (!amip)
return; return;
ti=amip->thread_id; CRYPTO_THREADID_cpy(&ti, &amip->threadid);
tip=amip->thread_idptr;
do do
{ {
int buf_len; int buf_len;
...@@ -733,8 +718,9 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) ...@@ -733,8 +718,9 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
ami_cnt++; ami_cnt++;
memset(buf,'>',ami_cnt); memset(buf,'>',ami_cnt);
BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt, BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
" thread=%lu/%p, file=%s, line=%d, info=\"", " thread=%lu, file=%s, line=%d, info=\"",
amip->thread_id, amip->thread_idptr, amip->file, amip->line); CRYPTO_THREADID_hash(&amip->threadid), amip->file,
amip->line);
buf_len=strlen(buf); buf_len=strlen(buf);
info_len=strlen(amip->info); info_len=strlen(amip->info);
if (128 - buf_len - 3 < info_len) if (128 - buf_len - 3 < info_len)
...@@ -754,7 +740,7 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l) ...@@ -754,7 +740,7 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
amip = amip->next; amip = amip->next;
} }
while(amip && amip->thread_id == ti && amip->thread_idptr == tip); while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
#ifdef LEVITTE_DEBUG_MEM #ifdef LEVITTE_DEBUG_MEM
if (amip) if (amip)
......
...@@ -145,8 +145,7 @@ static unsigned int crypto_lock_rand = 0; /* may be set only when a thread ...@@ -145,8 +145,7 @@ static unsigned int crypto_lock_rand = 0; /* may be set only when a thread
* holds CRYPTO_LOCK_RAND * holds CRYPTO_LOCK_RAND
* (to prevent double locking) */ * (to prevent double locking) */
/* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */ /* access to lockin_thread is synchronized by CRYPTO_LOCK_RAND2 */
static unsigned long locking_thread_id = 0; /* valid iff crypto_lock_rand is set */ static CRYPTO_THREADID locking_threadid; /* valid iff crypto_lock_rand is set */
static void *locking_thread_idptr = NULL; /* valid iff crypto_lock_rand is set */
#ifdef PREDICT #ifdef PREDICT
...@@ -214,8 +213,10 @@ static void ssleay_rand_add(const void *buf, int num, double add) ...@@ -214,8 +213,10 @@ static void ssleay_rand_add(const void *buf, int num, double add)
/* check if we already have the lock */ /* check if we already have the lock */
if (crypto_lock_rand) if (crypto_lock_rand)
{ {
CRYPTO_THREADID cur;
CRYPTO_THREADID_current(&cur);
CRYPTO_r_lock(CRYPTO_LOCK_RAND2); CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
do_not_lock = (locking_thread_id == CRYPTO_thread_id()) && (locking_thread_idptr == CRYPTO_thread_idptr()); do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
} }
else else
...@@ -373,8 +374,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num) ...@@ -373,8 +374,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
/* prevent ssleay_rand_bytes() from trying to obtain the lock again */ /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2); CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
locking_thread_id = CRYPTO_thread_id(); CRYPTO_THREADID_current(&locking_threadid);
locking_thread_idptr = CRYPTO_thread_idptr();
CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
crypto_lock_rand = 1; crypto_lock_rand = 1;
...@@ -529,15 +529,17 @@ static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num) ...@@ -529,15 +529,17 @@ static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
static int ssleay_rand_status(void) static int ssleay_rand_status(void)
{ {
CRYPTO_THREADID cur;
int ret; int ret;
int do_not_lock; int do_not_lock;
CRYPTO_THREADID_current(&cur);
/* check if we already have the lock /* check if we already have the lock
* (could happen if a RAND_poll() implementation calls RAND_status()) */ * (could happen if a RAND_poll() implementation calls RAND_status()) */
if (crypto_lock_rand) if (crypto_lock_rand)
{ {
CRYPTO_r_lock(CRYPTO_LOCK_RAND2); CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
do_not_lock = (locking_thread_id == CRYPTO_thread_id()) && (locking_thread_idptr == CRYPTO_thread_idptr()); do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
CRYPTO_r_unlock(CRYPTO_LOCK_RAND2); CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
} }
else else
...@@ -549,8 +551,7 @@ static int ssleay_rand_status(void) ...@@ -549,8 +551,7 @@ static int ssleay_rand_status(void)
/* prevent ssleay_rand_bytes() from trying to obtain the lock again */ /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2); CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
locking_thread_id = CRYPTO_thread_id(); CRYPTO_THREADID_cpy(&locking_threadid, &cur);
locking_thread_idptr = CRYPTO_thread_idptr();
CRYPTO_w_unlock(CRYPTO_LOCK_RAND2); CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
crypto_lock_rand = 1; crypto_lock_rand = 1;
} }
......
...@@ -264,6 +264,7 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) ...@@ -264,6 +264,7 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
{ {
BN_BLINDING *ret; BN_BLINDING *ret;
int got_write_lock = 0; int got_write_lock = 0;
CRYPTO_THREADID cur;
CRYPTO_r_lock(CRYPTO_LOCK_RSA); CRYPTO_r_lock(CRYPTO_LOCK_RSA);
...@@ -281,7 +282,8 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) ...@@ -281,7 +282,8 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
if (ret == NULL) if (ret == NULL)
goto err; goto err;
if ((BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id()) && (BN_BLINDING_get_thread_idptr(ret) == CRYPTO_thread_idptr())) CRYPTO_THREADID_current(&cur);
if (!CRYPTO_THREADID_cmp(&cur, BN_BLINDING_thread_id(ret)))
{ {
/* rsa->blinding is ours! */ /* rsa->blinding is ours! */
......
...@@ -417,8 +417,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) ...@@ -417,8 +417,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB); RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB);
goto err; goto err;
} }
BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id()); CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret));
BN_BLINDING_set_thread_idptr(ret, CRYPTO_thread_idptr());
err: err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
if (in_ctx == NULL) if (in_ctx == NULL)
......
...@@ -328,7 +328,7 @@ int main(int argc, char *argv[]) ...@@ -328,7 +328,7 @@ int main(int argc, char *argv[])
} }
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks_fp(stderr); CRYPTO_mem_leaks_fp(stderr);
......
...@@ -22,8 +22,11 @@ functions. ...@@ -22,8 +22,11 @@ functions.
BN_CTX *ctx); BN_CTX *ctx);
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
BN_CTX *ctx); BN_CTX *ctx);
#ifndef OPENSSL_NO_DEPRECATED
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *); unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long); void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
#endif
CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
...@@ -54,11 +57,11 @@ BN_BLINDING_convert() and BN_BLINDING_invert() are wrapper ...@@ -54,11 +57,11 @@ BN_BLINDING_convert() and BN_BLINDING_invert() are wrapper
functions for BN_BLINDING_convert_ex() and BN_BLINDING_invert_ex() functions for BN_BLINDING_convert_ex() and BN_BLINDING_invert_ex()
with B<r> set to NULL. with B<r> set to NULL.
BN_BLINDING_set_thread_id() and BN_BLINDING_get_thread_id() BN_BLINDING_thread_id() provides access to the B<CRYPTO_THREADID>
set and get the "thread id" value of the B<BN_BLINDING> structure, object within the B<BN_BLINDING> structure. This is to help users
a field provided to users of B<BN_BLINDING> structure to help them provide proper locking if needed for multi-threaded use. The "thread
provide proper locking if needed for multi-threaded use. The id" object of a newly allocated B<BN_BLINDING> structure is
"thread id" of a newly allocated B<BN_BLINDING> structure is zero. initialised to the thread id in which BN_BLINDING_new() was called.
BN_BLINDING_get_flags() returns the BN_BLINDING flags. Currently BN_BLINDING_get_flags() returns the BN_BLINDING flags. Currently
there are two supported flags: B<BN_BLINDING_NO_UPDATE> and there are two supported flags: B<BN_BLINDING_NO_UPDATE> and
...@@ -83,8 +86,8 @@ BN_BLINDING_update(), BN_BLINDING_convert(), BN_BLINDING_invert(), ...@@ -83,8 +86,8 @@ BN_BLINDING_update(), BN_BLINDING_convert(), BN_BLINDING_invert(),
BN_BLINDING_convert_ex() and BN_BLINDING_invert_ex() return 1 on BN_BLINDING_convert_ex() and BN_BLINDING_invert_ex() return 1 on
success and 0 if an error occured. success and 0 if an error occured.
BN_BLINDING_get_thread_id() returns the thread id (a B<unsigned long> BN_BLINDING_thread_id() returns a pointer to the thread id object
value) or 0 if not set. within a B<BN_BLINDING> object.
BN_BLINDING_get_flags() returns the currently set B<BN_BLINDING> flags BN_BLINDING_get_flags() returns the currently set B<BN_BLINDING> flags
(a B<unsigned long> value). (a B<unsigned long> value).
...@@ -98,6 +101,9 @@ L<bn(3)|bn(3)> ...@@ -98,6 +101,9 @@ L<bn(3)|bn(3)>
=head1 HISTORY =head1 HISTORY
BN_BLINDING_thread_id was first introduced in OpenSSL 0.9.9, and it
deprecates BN_BLINDING_set_thread_id and BN_BLINDING_get_thread_id.
BN_BLINDING_convert_ex, BN_BLINDIND_invert_ex, BN_BLINDING_get_thread_id, BN_BLINDING_convert_ex, BN_BLINDIND_invert_ex, BN_BLINDING_get_thread_id,
BN_BLINDING_set_thread_id, BN_BLINDING_set_flags, BN_BLINDING_get_flags BN_BLINDING_set_thread_id, BN_BLINDING_set_flags, BN_BLINDING_get_flags
and BN_BLINDING_create_param were first introduced in OpenSSL 0.9.8 and BN_BLINDING_create_param were first introduced in OpenSSL 0.9.8
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
=head1 NAME =head1 NAME
CRYPTO_set_locking_callback, CRYPTO_set_id_callback, CRYPTO_THREADID_set_callback, CRYPTO_THREADID_get_callback,
CRYPTO_set_idptr_callback, CRYPTO_num_locks, CRYPTO_THREADID_current, CRYPTO_THREADID_cmp, CRYPTO_THREADID_cpy,
CRYPTO_THREADID_hash, CRYPTO_set_locking_callback, CRYPTO_num_locks,
CRYPTO_set_dynlock_create_callback, CRYPTO_set_dynlock_lock_callback, CRYPTO_set_dynlock_create_callback, CRYPTO_set_dynlock_lock_callback,
CRYPTO_set_dynlock_destroy_callback, CRYPTO_get_new_dynlockid, CRYPTO_set_dynlock_destroy_callback, CRYPTO_get_new_dynlockid,
CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
...@@ -12,16 +13,26 @@ CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support ...@@ -12,16 +13,26 @@ CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
#include <openssl/crypto.h> #include <openssl/crypto.h>
void CRYPTO_set_locking_callback(void (*locking_function)(int mode, /* Don't use this structure directly. */
int n, const char *file, int line)); typedef struct crypto_threadid_st
{
void CRYPTO_set_id_callback(unsigned long (*id_function)(void)); void *ptr;
unsigned long val;
void CRYPTO_set_idptr_callback(void *(*idptr_function)(void)); } CRYPTO_THREADID;
/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */
void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val);
void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr);
int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID *));
void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *);
void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a,
const CRYPTO_THREADID *b);
void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest,
const CRYPTO_THREADID *src);
unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
int CRYPTO_num_locks(void); int CRYPTO_num_locks(void);
/* struct CRYPTO_dynlock_value needs to be defined by the user */ /* struct CRYPTO_dynlock_value needs to be defined by the user */
struct CRYPTO_dynlock_value; struct CRYPTO_dynlock_value;
...@@ -53,7 +64,8 @@ CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support ...@@ -53,7 +64,8 @@ CRYPTO_destroy_dynlockid, CRYPTO_lock - OpenSSL thread support
=head1 DESCRIPTION =head1 DESCRIPTION
OpenSSL can safely be used in multi-threaded applications provided OpenSSL can safely be used in multi-threaded applications provided
that at least two callback functions are set. that at least two callback functions are set, locking_function and
threadid_func.
locking_function(int mode, int n, const char *file, int line) is locking_function(int mode, int n, const char *file, int line) is
needed to perform locking on shared data structures. needed to perform locking on shared data structures.
...@@ -68,17 +80,42 @@ B<CRYPTO_LOCK>, and releases it otherwise. ...@@ -68,17 +80,42 @@ B<CRYPTO_LOCK>, and releases it otherwise.
B<file> and B<line> are the file number of the function setting the B<file> and B<line> are the file number of the function setting the
lock. They can be useful for debugging. lock. They can be useful for debugging.
id_function(void) is a function that returns a numerical thread ID, threadid_func(CRYPTO_THREADID *id) is needed to record the currently-executing
for example pthread_self() if it returns an integer (see NOTES below). thread's identifier into B<id>. The implementation of this callback should not
By OpenSSL's defaults, this is not needed on Windows nor on platforms fill in B<id> directly, but should use CRYPTO_THREADID_set_numeric() if thread
where getpid() returns a different ID for each thread (see NOTES IDs are numeric, or CRYPTO_THREADID_set_pointer() if they are pointer-based.
below). If the application does not register such a callback using
CRYPTO_THREADID_set_callback(), then a default implementation is used - on
Windows and BeOS this uses the system's default thread identifying APIs, and on
all other platforms it uses the address of B<errno>. The latter is satisfactory
for thread-safety if and only if the platform has a thread-local error number
facility.
idptr_function(void) is a function that similarly returns a thread ID, Once threadid_func() is registered, or if the built-in default implementation is
but of type void *. This is not needed on platforms where &errno is to be used;
different for each thread. OpenSSL assumes that it is in the same
thread iff both the numerical and the pointer thread ID agree, so it =over 4
suffices to define one of these two callback functions appropriately.
=item *
CRYPTO_THREADID_current() records the currently-executing thread ID into the
given B<id> object.
=item *
CRYPTO_THREADID_cmp() compares two thread IDs (returning zero for equality, ie.
the same semantics as memcmp()).
=item *
CRYPTO_THREADID_cpy() duplicates a thread ID value,
=item *
CRYPTO_THREADID_hash() returns a numeric value usable as a hash-table key. This
is usually the exact numeric or pointer-based thread ID used internally, however
this also handles the unusual case where pointers are larger than 'long'
variables and the platform's thread IDs are pointer-based - in this case, mixing
is done to attempt to produce a unique numeric value even though it is not as
wide as the platform's true thread IDs.
=back
Additionally, OpenSSL supports dynamic locks, and sometimes, some parts Additionally, OpenSSL supports dynamic locks, and sometimes, some parts
of OpenSSL need it for better performance. To enable this, the following of OpenSSL need it for better performance. To enable this, the following
...@@ -150,24 +187,6 @@ You can find out if OpenSSL was configured with thread support: ...@@ -150,24 +187,6 @@ You can find out if OpenSSL was configured with thread support:
Also, dynamic locks are currently not used internally by OpenSSL, but Also, dynamic locks are currently not used internally by OpenSSL, but
may do so in the future. may do so in the future.
Defining id_function(void) has it's own issues. Generally speaking,
pthread_self() should be used, even on platforms where getpid() gives
different answers in each thread, since that may depend on the machine
the program is run on, not the machine where the program is being
compiled. For instance, Red Hat 8 Linux and earlier used
LinuxThreads, whose getpid() returns a different value for each
thread. Red Hat 9 Linux and later use NPTL, which is
Posix-conformant, and has a getpid() that returns the same value for
all threads in a process. A program compiled on Red Hat 8 and run on
Red Hat 9 will therefore see getpid() returning the same value for
all threads.
There is still the issue of platforms where pthread_self() returns
something other than an integer. It is for cases like this that
CRYPTO_set_idptr_callback() comes in handy. (E.g., call malloc(1)
once in each thread, and have idptr_function() return a pointer to
this object.)
=head1 EXAMPLES =head1 EXAMPLES
B<crypto/threads/mttest.c> shows examples of the callback functions on B<crypto/threads/mttest.c> shows examples of the callback functions on
...@@ -179,8 +198,10 @@ CRYPTO_set_locking_callback() and CRYPTO_set_id_callback() are ...@@ -179,8 +198,10 @@ CRYPTO_set_locking_callback() and CRYPTO_set_id_callback() are
available in all versions of SSLeay and OpenSSL. available in all versions of SSLeay and OpenSSL.
CRYPTO_num_locks() was added in OpenSSL 0.9.4. CRYPTO_num_locks() was added in OpenSSL 0.9.4.
All functions dealing with dynamic locks were added in OpenSSL 0.9.5b-dev. All functions dealing with dynamic locks were added in OpenSSL 0.9.5b-dev.
B<CRYPTO_THREADID> and associated functions were introduced in OpenSSL 0.9.9
CRYPTO_set_idptr_callback() was added in OpenSSL 0.9.9. to replace (actually, deprecate) the previous CRYPTO_set_id_callback(),
CRYPTO_get_id_callback(), and CRYPTO_thread_id() functions which assumed
thread IDs to always be represented by 'unsigned long'.
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -1014,7 +1014,7 @@ end: ...@@ -1014,7 +1014,7 @@ end:
#endif #endif
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
ERR_free_strings(); ERR_free_strings();
ERR_remove_state(0); ERR_remove_thread_state(NULL);
EVP_cleanup(); EVP_cleanup();
CRYPTO_mem_leaks(bio_err); CRYPTO_mem_leaks(bio_err);
if (bio_err != NULL) BIO_free(bio_err); if (bio_err != NULL) BIO_free(bio_err);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册