Skip to content

Commit

Permalink
Remove the dual-callback scheme for numeric and pointer thread IDs,
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Geoff Thorpe committed Aug 6, 2008
1 parent 96826bf commit 4c32969
Show file tree
Hide file tree
Showing 25 changed files with 338 additions and 217 deletions.
48 changes: 24 additions & 24 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@

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
simple case where the self issued certificates in the chain exist and
the real CRL issuer is higher in the existing chain.
Expand Down Expand Up @@ -307,30 +331,6 @@
list-message-digest-algorithms and list-cipher-algorithms.
[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
of degrees of non-zero coefficients is now terminated with -1.
Previously it was terminated with 0, which was also part of the
Expand Down
4 changes: 1 addition & 3 deletions FAQ
Original file line number Diff line number Diff line change
Expand Up @@ -717,9 +717,7 @@ file.

Multi-threaded applications must provide two callback functions to
OpenSSL by calling CRYPTO_set_locking_callback() and
CRYPTO_set_id_callback(). (For OpenSSL 0.9.9 or later, the new
function CRYPTO_set_idptr_callback() may be used in place of
CRYPTO_set_id_callback().) This is described in the threads(3)
CRYPTO_set_id_callback(). This is described in the threads(3)
manpage.

* I've compiled a program under Windows and it crashes: why?
Expand Down
4 changes: 2 additions & 2 deletions apps/apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ extern BIO *bio_err;
# define apps_shutdown() \
do { CONF_modules_unload(1); destroy_ui_method(); \
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)
# else
# define apps_startup() \
Expand All @@ -191,7 +191,7 @@ extern BIO *bio_err;
# define apps_shutdown() \
do { CONF_modules_unload(1); destroy_ui_method(); \
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)
# endif
#endif
Expand Down
6 changes: 4 additions & 2 deletions crypto/bn/bn.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
#include <stdio.h> /* FILE */
#endif
#include <openssl/ossl_typ.h>
#include <openssl/crypto.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -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_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 *);
#ifndef OPENSSL_NO_DEPRECATED
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
void *BN_BLINDING_get_thread_idptr(const BN_BLINDING *);
void BN_BLINDING_set_thread_idptr(BN_BLINDING *, void *);
#endif
CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
Expand Down
17 changes: 8 additions & 9 deletions crypto/bn/bn_blind.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ struct bn_blinding_st
BIGNUM *Ai;
BIGNUM *e;
BIGNUM *mod; /* just a reference */
#ifndef OPENSSL_NO_DEPRECATED
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 */
void *thread_idptr; /* added in OpenSSL 0.9.9;
* used only by crypto/rsa/rsa_eay.c, rsa_lib.c */
#endif
CRYPTO_THREADID tid;
unsigned int counter;
unsigned long flags;
BN_MONT_CTX *m_ctx;
Expand Down Expand Up @@ -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);

ret->counter = BN_BLINDING_COUNTER;
CRYPTO_THREADID_current(&ret->tid);
return(ret);
err:
if (ret != NULL) BN_BLINDING_free(ret);
Expand Down Expand Up @@ -265,6 +267,7 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ct
return(ret);
}

#ifndef OPENSSL_NO_DEPRECATED
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b)
{
return b->thread_id;
Expand All @@ -274,15 +277,11 @@ void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long 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;
}

void BN_BLINDING_set_thread_idptr(BN_BLINDING *b, void *p)
{
b->thread_idptr = p;
return &b->tid;
}

unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
Expand Down
2 changes: 1 addition & 1 deletion crypto/bn/exptest.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ int main(int argc, char *argv[])
BN_free(b);
BN_free(m);
BN_CTX_free(ctx);
ERR_remove_state(0);
ERR_remove_thread_state(NULL);
CRYPTO_mem_leaks(out);
BIO_free(out);
printf(" done\n");
Expand Down
152 changes: 122 additions & 30 deletions crypto/cryptlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ static void (MS_FAR *locking_callback)(int mode,int type,
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,
Expand Down Expand Up @@ -414,6 +416,108 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
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)
{
return(id_callback);
Expand Down Expand Up @@ -446,33 +550,13 @@ unsigned long CRYPTO_thread_id(void)
ret=id_callback();
return(ret);
}

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;
}
#endif

void CRYPTO_lock(int mode, int type, const char *file, int line)
{
#ifdef LOCK_DEBUG
{
CRYPTO_THREADID id;
char *rw_text,*operation_text;

if (mode & CRYPTO_LOCK)
Expand All @@ -489,8 +573,9 @@ void CRYPTO_lock(int mode, int type, const char *file, int line)
else
rw_text="ERROR";

fprintf(stderr,"lock:%08lx/%08p:(%s)%s %-18s %s:%d\n",
CRYPTO_thread_id(), CRYPTO_thread_idptr(), rw_text, operation_text,
CRYPTO_THREADID_current(&id);
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);
}
#endif
Expand Down Expand Up @@ -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);
#ifdef LOCK_DEBUG
fprintf(stderr,"ladd:%08lx/%0xp:%2d+%2d->%2d %-18s %s:%d\n",
CRYPTO_thread_id(), CRYPTO_thread_idptr(),
before,amount,ret,
{
CRYPTO_THREADID id;
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),
file,line);
}
#endif
}
else
Expand All @@ -539,11 +627,15 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,

ret= *pointer+amount;
#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,
CRYPTO_get_lock_name(type),
file,line);
}
#endif
*pointer=ret;
CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line);
Expand Down
Loading

0 comments on commit 4c32969

Please sign in to comment.