There was a need to support thread ID types that couldn't be reliably cast
authorGeoff Thorpe <geoff@openssl.org>
Fri, 28 Mar 2008 02:49:43 +0000 (02:49 +0000)
committerGeoff Thorpe <geoff@openssl.org>
Fri, 28 Mar 2008 02:49:43 +0000 (02:49 +0000)
to 'unsigned long' (ie. odd platforms/compilers), so a pointer-typed
version was added but it required portable code to check *both* modes to
determine equality. This commit maintains the availability of both thread
ID types, but deprecates the type-specific accessor APIs that invoke the
callbacks - instead a single type-independent API is used.  This simplifies
software that calls into this interface, and should also make it less
error-prone - as forgetting to call and compare *both* thread ID accessors
could have led to hard-to-debug/infrequent bugs (that might only affect
certain platforms or thread implementations). As the CHANGES note says,
there were corresponding deprecations and replacements in the
thread-related functions for BN_BLINDING and ERR too.

25 files changed:
CHANGES
apps/apps.h
crypto/bn/bn.h
crypto/bn/bn_blind.c
crypto/bn/exptest.c
crypto/cryptlib.c
crypto/crypto.h
crypto/dsa/dsatest.c
crypto/ec/ectest.c
crypto/ecdh/ecdhtest.c
crypto/ecdsa/ecdsatest.c
crypto/engine/enginetest.c
crypto/err/err.c
crypto/err/err.h
crypto/err/err_prn.c
crypto/evp/evp_test.c
crypto/mem_dbg.c
crypto/rand/md_rand.c
crypto/rsa/rsa_eay.c
crypto/rsa/rsa_lib.c
crypto/rsa/rsa_test.c
doc/crypto/BN_BLINDING_new.pod
doc/crypto/bn.pod
doc/crypto/threads.pod
ssl/ssltest.c

diff --git a/CHANGES b/CHANGES
index bf448fa..40c163b 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,58 @@
 
  Changes between 0.9.8g and 0.9.9  [xx XXX xxxx]
 
+  *) To support arbitrarily-typed thread IDs, deprecate the existing
+     type-specific APIs for a general purpose CRYPTO_THREADID
+     interface. Applications can choose the thread ID
+     callback type it wishes to register, as before;
+
+        void CRYPTO_set_id_callback(unsigned long (*func)(void));
+        void CRYPTO_set_idptr_callback(void *(*func)(void));
+
+     but retrieval, copies, and comparisons of thread IDs are via
+     type-independent interfaces;
+
+        void CRYPTO_THREADID_set(CRYPTO_THREADID *id);
+        void CRYPTO_THREADID_cmp(const CRYPTO_THREADID *id1,
+                                 const CRYPTO_THREADID *id2);
+        void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dst,
+                                 const CRYPTO_THREADID *src);
+
+     Also, for code that needs a thread ID "value" for use in
+     hash-tables or logging, a "hash" is available by;
+
+        unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
+
+     This hash value is likely to be the thread ID anyway, but
+     otherwise it will be unique if possible or as collision-free as
+     possible if uniqueness can't be guaranteed on the target
+     architecture.
+
+     The following functions are deprecated;
+        unsigned long (*CRYPTO_get_id_callback(void))(void);
+        unsigned long CRYPTO_thread_id(void);
+
+     As a consequence of the above, there are similar deprecations of
+     BN_BLINDING functions in favour of CRYPTO_THREADID-based
+     alternatives;
+
+        #ifndef OPENSSL_NO_DEPRECATED
+        unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
+        void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
+        #endif
+        void BN_BLINDING_set_thread(BN_BLINDING *);
+        int BN_BLINDING_cmp_thread(const BN_BLINDING *, const
+                                   CRYPTO_THREADID *);
+
+     Also, the ERR_remove_state(int pid) API has been deprecated;
+
+        #ifndef OPENSSL_NO_DEPRECATED
+        void ERR_remove_state(unsigned long pid)
+        #endif
+        void ERR_remove_thread_state(CRYPTO_THREADID *tid);
+
+     [Geoff Thorpe]
+
   *) Initial support for Cryptographic Message Syntax (aka CMS) based
      on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
      support for data, signedData, compressedData, digestedData and
      callback is &errno.
      [Bodo Moeller]
 
+     -- NOTE -- this change has been reverted and replaced with a
+     type-independent wrapper (ie. applications do not have to check
+     two type-specific thread ID representations as implied in this
+     change note). However, the "idptr" callback form described here
+     can still be registered. Please see the more recent CHANGES note
+     regarding CRYPTO_THREADID. [Geoff Thorpe]
+     -- NOTE --
+
   *) 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
index 6786cbd..d446d17 100644 (file)
@@ -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() \
@@ -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
index 83f87ff..56d9f5f 100644 (file)
 #ifndef OPENSSL_NO_FP_API
 #include <stdio.h> /* FILE */
 #endif
+#include <openssl/crypto.h>
 #include <openssl/ossl_typ.h>
 
 #ifdef  __cplusplus
@@ -563,10 +564,12 @@ 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
+void BN_BLINDING_set_thread(BN_BLINDING *);
+int BN_BLINDING_cmp_thread(const BN_BLINDING *, const CRYPTO_THREADID *);
 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,
index e9b6173..fa48470 100644 (file)
@@ -121,10 +121,13 @@ struct bn_blinding_st
        BIGNUM *Ai;
        BIGNUM *e;
        BIGNUM *mod; /* just a reference */
+/* FIXME: should really try to remove these, but the deprecated APIs that are
+ * using them would need to be fudged somehow. */
+#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;
@@ -265,6 +268,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;
@@ -274,15 +278,16 @@ 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)
+void BN_BLINDING_set_thread(BN_BLINDING *b)
        {
-       return b->thread_idptr;
+       CRYPTO_THREADID_set(&b->tid);
        }
 
-void BN_BLINDING_set_thread_idptr(BN_BLINDING *b, void *p)
+int BN_BLINDING_cmp_thread(const BN_BLINDING *b, const CRYPTO_THREADID *tid)
        {
-       b->thread_idptr = p;
+       return CRYPTO_THREADID_cmp(&b->tid, tid);
        }
 
 unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
index 89ebcc8..074a8e8 100644 (file)
@@ -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");
index 33c70af..73bdfd8 100644 (file)
@@ -415,16 +415,61 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
        add_lock_callback=func;
        }
 
-unsigned long (*CRYPTO_get_id_callback(void))(void)
-       {
-       return(id_callback);
-       }
+/* 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(). */
 
 void CRYPTO_set_id_callback(unsigned long (*func)(void))
        {
        id_callback=func;
        }
 
+void CRYPTO_set_idptr_callback(void *(*func)(void))
+       {
+       idptr_callback=func;
+       }
+
+void CRYPTO_THREADID_set(CRYPTO_THREADID *id)
+       {
+       memset(id, 0, sizeof(*id));
+       if (idptr_callback)
+               id->ptr = idptr_callback();
+       else if (id_callback)
+               id->ulong = id_callback();
+       else
+               id->ptr = &errno;
+       }
+
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *id1, const CRYPTO_THREADID *id2)
+       {
+       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;
+       }
+
+unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
+       {
+       if (idptr_callback || !id_callback)
+               return (unsigned long)id->ptr;
+       return id->ulong;
+       }
+
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dst, const CRYPTO_THREADID *src)
+       {
+       memcpy(dst, src, sizeof(*src));
+       }
+
+#ifndef OPENSSL_NO_DEPRECATED
+unsigned long (*CRYPTO_get_id_callback(void))(void)
+       {
+       return(id_callback);
+       }
+
 unsigned long CRYPTO_thread_id(void)
        {
        unsigned long ret=0;
@@ -447,34 +492,14 @@ 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
                {
                char *rw_text,*operation_text;
+               CRYPTO_THREADID tid;
 
                if (mode & CRYPTO_LOCK)
                        operation_text="lock  ";
@@ -490,8 +515,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_set(&tid);
+               fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n",
+                       CRYPTO_THREADID_hash(&tid), rw_text, operation_text,
                        CRYPTO_get_lock_name(type), file, line);
                }
 #endif
@@ -518,6 +544,10 @@ int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
             int line)
        {
        int ret = 0;
+#ifdef LOCK_DEBUG
+       CRYPTO_THREADID tid;
+       CRYPTO_THREADID_set(&tid);
+#endif
 
        if (add_lock_callback != NULL)
                {
@@ -527,9 +557,8 @@ 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,
+               fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
+                       CRYPTO_THREADID_hash(&tid), before,amount,ret,
                        CRYPTO_get_lock_name(type),
                        file,line);
 #endif
@@ -540,9 +569,8 @@ 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(),
-                       *pointer,amount,ret,
+               fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n",
+                       CRYPTO_THREADID_hash(&tid), *pointer,amount,ret,
                        CRYPTO_get_lock_name(type),
                        file,line);
 #endif
index ffe9299..bb9b89c 100644 (file)
@@ -300,6 +300,17 @@ typedef struct crypto_ex_data_func_st
 
 DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
 
+/* This structure is exposed to allow it to be used without dynamic allocation,
+ * however it exists to encapsulate the different ways of representing "thread
+ * ID"s (given that applications provide the thread implementation via
+ * callbacks). So treat this type as opaque if you don't want your code to fall
+ * apart when someone decides to extend this in some way. */
+typedef struct crypto_threadid
+       {
+       void *ptr;
+       unsigned long ulong;
+       } CRYPTO_THREADID;
+
 /* Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA
  * entry.
  */
@@ -420,12 +431,27 @@ void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type,
                                              const char *file, int line));
 int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type,
                                          const char *file,int line);
+/* Implement "thread ID" via callback, choose the prototype that matches your
+ * thread implementation. */
 void CRYPTO_set_id_callback(unsigned long (*func)(void));
+void CRYPTO_set_idptr_callback(void *(*func)(void));
+/* Records the thread ID of the currently executing thread */
+void CRYPTO_THREADID_set(CRYPTO_THREADID *id);
+/* Compares two thread IDs. If the underlying notion of thread ID is linear,
+ * this returns -1, 0, or +1 to imply strict-ordering (as other ***_cmp()
+ * functions do). Otherwise, zero means equal, non-zero means not equal. */
+int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *id1, const CRYPTO_THREADID *id2);
+/* When you need "a number", eg. for hashing, use this. */
+unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id);
+/* Copy a threadid */
+void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dst, const CRYPTO_THREADID *src);
+#ifndef OPENSSL_NO_DEPRECATED
+/* Deprecated interfaces - these presume you know exactly what's going on under
+ * the covers. Better to migrate to the CRYPTO_THREADID_***() form. */
 unsigned long (*CRYPTO_get_id_callback(void))(void);
 unsigned long CRYPTO_thread_id(void);
-void CRYPTO_set_idptr_callback(void *(*func)(void));
-void *(*CRYPTO_get_idptr_callback(void))(void);
-void *CRYPTO_thread_idptr(void);
+#endif
+
 const char *CRYPTO_get_lock_name(int type);
 int CRYPTO_add_lock(int *pointer,int amount,int type, const char *file,
                    int line);
index 5a699ca..edffd24 100644 (file)
@@ -222,7 +222,7 @@ end:
                ERR_print_errors(bio_err);
        if (dsa != NULL) DSA_free(dsa);
        CRYPTO_cleanup_all_ex_data();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        ERR_free_strings();
        CRYPTO_mem_leaks(bio_err);
        if (bio_err != NULL)
index b74d643..7509cb9 100644 (file)
@@ -1326,7 +1326,7 @@ int main(int argc, char *argv[])
 #endif
        CRYPTO_cleanup_all_ex_data();
        ERR_free_strings();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        CRYPTO_mem_leaks_fp(stderr);
        
        return 0;
index 1575006..212a87e 100644 (file)
@@ -343,7 +343,7 @@ err:
        if (ctx) BN_CTX_free(ctx);
        BIO_free(out);
        CRYPTO_cleanup_all_ex_data();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        CRYPTO_mem_leaks_fp(stderr);
        EXIT(ret);
        return(ret);
index b07e312..aa4e148 100644 (file)
@@ -490,7 +490,7 @@ err:
        if (ret)
                ERR_print_errors(out);
        CRYPTO_cleanup_all_ex_data();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        ERR_free_strings();
        CRYPTO_mem_leaks(out);
        if (out != NULL)
index cf82f49..3c1d2b4 100644 (file)
@@ -276,7 +276,7 @@ end:
        ENGINE_cleanup();
        CRYPTO_cleanup_all_ex_data();
        ERR_free_strings();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        CRYPTO_mem_leaks_fp(stderr);
        return to_return;
        }
index 09b9812..8adcd9f 100644 (file)
@@ -975,50 +975,47 @@ static int err_cmp(const void *a_void, const void *b_void)
 /* static unsigned long pid_hash(ERR_STATE *a) */
 static unsigned long pid_hash(const void *a_void)
        {
-       return((((const ERR_STATE *)a_void)->pid + (unsigned long)((const ERR_STATE *)a_void)->pidptr)*13);
+       return CRYPTO_THREADID_hash(&((const ERR_STATE *)a_void)->tid);
        }
 
 /* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
 static int pid_cmp(const void *a_void, const void *b_void)
        {
-       return (((const ERR_STATE *)a_void)->pid != ((const ERR_STATE *)b_void)->pid)
-              || (((const ERR_STATE *)a_void)->pidptr != ((const ERR_STATE *)b_void)->pidptr);
+       return CRYPTO_THREADID_cmp(&((const ERR_STATE *)a_void)->tid,
+                               &((const ERR_STATE *)b_void)->tid);
        }
 
-void ERR_remove_state(unsigned long pid)
+void ERR_remove_thread_state(CRYPTO_THREADID *tid)
        {
        ERR_STATE tmp;
-       void *pidptr;
 
-       err_fns_check();
-       if (pid != 0)
-               pidptr = &errno;
+       if (tid)
+               CRYPTO_THREADID_cpy(&tmp.tid, tid);
        else
-               {
-               pid = CRYPTO_thread_id();
-               pidptr = CRYPTO_thread_idptr();
-               }
-       
-       tmp.pid=pid;
-       tmp.pidptr=pidptr;
+               CRYPTO_THREADID_set(&tmp.tid);
+       err_fns_check();
        /* thread_del_item automatically destroys the LHASH if the number of
         * items reaches zero. */
        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)
        {
        static ERR_STATE fallback;
+       CRYPTO_THREADID tid;
        ERR_STATE *ret,tmp,*tmpp=NULL;
        int i;
-       unsigned long pid;
-       void *pidptr;
 
        err_fns_check();
-       pid = CRYPTO_thread_id();
-       pidptr = CRYPTO_thread_idptr();
-       tmp.pid = pid;
-       tmp.pidptr = pidptr;
+       CRYPTO_THREADID_set(&tid);
+       CRYPTO_THREADID_cpy(&tmp.tid, &tid);
        ret=ERRFN(thread_get_item)(&tmp);
 
        /* ret == the error state, if NULL, make a new one */
@@ -1026,8 +1023,7 @@ ERR_STATE *ERR_get_state(void)
                {
                ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
                if (ret == NULL) return(&fallback);
-               ret->pid=pid;
-               ret->pidptr=pidptr;
+               CRYPTO_THREADID_cpy(&ret->tid, &tid);
                ret->top=0;
                ret->bottom=0;
                for (i=0; i<ERR_NUM_ERRORS; i++)
index 9a6aecf..c56f5aa 100644 (file)
@@ -147,8 +147,10 @@ extern "C" {
 #define ERR_NUM_ERRORS 16
 typedef struct err_state_st
        {
+#ifndef OPENSSL_NO_DEPRECATED
        unsigned long pid;
-       void *pidptr; /* new in OpenSSL 0.9.9 */
+#endif
+       CRYPTO_THREADID tid;
        int err_flags[ERR_NUM_ERRORS];
        unsigned long err_buffer[ERR_NUM_ERRORS];
        char *err_data[ERR_NUM_ERRORS];
@@ -349,7 +351,10 @@ void ERR_load_ERR_strings(void);
 void ERR_load_crypto_strings(void);
 void ERR_free_strings(void);
 
+void ERR_remove_thread_state(CRYPTO_THREADID *tid);
+#ifndef OPENSSL_NO_DEPRECATED
 void ERR_remove_state(unsigned long pid); /* if zero we look it up */
+#endif
 ERR_STATE *ERR_get_state(void);
 
 #ifndef OPENSSL_NO_LHASH
index 2224a90..6515d10 100644 (file)
@@ -72,8 +72,10 @@ void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u),
        const char *file,*data;
        int line,flags;
        unsigned long es;
+       CRYPTO_THREADID tid;
 
-       es=CRYPTO_thread_id();
+       CRYPTO_THREADID_set(&tid);
+       es = CRYPTO_THREADID_hash(&tid);
        while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
                {
                ERR_error_string_n(l, buf, sizeof buf);
index bb6f02c..b8c9235 100644 (file)
@@ -441,7 +441,7 @@ int main(int argc,char **argv)
 #endif
     EVP_cleanup();
     CRYPTO_cleanup_all_ex_data();
-    ERR_remove_state(0);
+    ERR_remove_thread_state(NULL);
     ERR_free_strings();
     CRYPTO_mem_leaks_fp(stderr);
 
index 5e55d22..1d94d3c 100644 (file)
@@ -146,9 +146,8 @@ typedef struct app_mem_info_st
  *   CRYPTO_pop_info()           to pop an entry,
  *   CRYPTO_remove_all_info()    to pop all entries.
  */
-       {       
-       unsigned long thread_id;
-       void *thread_idptr;
+       {
+       CRYPTO_THREADID threadid;
        const char *file;
        int line;
        const char *info;
@@ -170,8 +169,7 @@ typedef struct mem_st
        int num;
        const char *file;
        int line;
-       unsigned long thread_id;
-       void *thread_idptr;
+       CRYPTO_THREADID threadid;
        unsigned long order;
        time_t time;
        APP_INFO *app_info;
@@ -192,12 +190,9 @@ static unsigned int num_disable = 0; /* num_disable > 0
                                       * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
                                       */
 
-/* The following two variables, disabling_thread_id and disabling_thread_idptr,
- * are valid iff num_disable > 0.  CRYPTO_LOCK_MALLOC2 is locked exactly in
- * this case (by the thread named in disabling_thread_id / disabling_thread_idptr).
- */
-static unsigned long disabling_thread_id = 0;
-static void *disabling_thread_idptr = NULL;
+/* Valid iff num_disable > 0.  CRYPTO_LOCK_MALLOC2 is locked exactly in this
+ * case (by the thread named in disabling_threadid). */
+static CRYPTO_THREADID disabling_threadid;
 
 static void app_info_free(APP_INFO *inf)
        {
@@ -234,9 +229,10 @@ int CRYPTO_mem_ctrl(int mode)
        case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
                if (mh_mode & CRYPTO_MEM_CHECK_ON)
                        {
-                       if (!num_disable
-                           || (disabling_thread_id != CRYPTO_thread_id())
-                           || (disabling_thread_idptr != CRYPTO_thread_idptr())) /* otherwise we already have the MALLOC2 lock */
+                       CRYPTO_THREADID tid;
+                       CRYPTO_THREADID_set(&tid);
+                       if (!num_disable || CRYPTO_THREADID_cmp(&tid,
+                                               &disabling_threadid))
                                {
                                /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
                                 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
@@ -254,8 +250,7 @@ int CRYPTO_mem_ctrl(int mode)
                                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
                                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
                                mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
-                               disabling_thread_id=CRYPTO_thread_id();
-                               disabling_thread_idptr=CRYPTO_thread_idptr();
+                               CRYPTO_THREADID_set(&disabling_threadid);
                                }
                        num_disable++;
                        }
@@ -288,11 +283,12 @@ int CRYPTO_is_mem_check_on(void)
 
        if (mh_mode & CRYPTO_MEM_CHECK_ON)
                {
+               CRYPTO_THREADID tid;
+               CRYPTO_THREADID_set(&tid);
                CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
 
-               ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
-                       || (disabling_thread_id != CRYPTO_thread_id())
-                       || (disabling_thread_idptr != CRYPTO_thread_idptr());
+               ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE) ||
+                       CRYPTO_THREADID_cmp(&tid, &disabling_threadid);
 
                CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
                }
@@ -339,20 +335,15 @@ static unsigned long mem_hash(const void *a_void)
 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
 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)
-              || (((const APP_INFO *)a_void)->thread_idptr != ((const APP_INFO *)b_void)->thread_idptr);
+       return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
+                               &((const APP_INFO *)b_void)->threadid);
        }
 
 /* static unsigned long app_info_hash(APP_INFO *a) */
 static unsigned long app_info_hash(const void *a_void)
        {
-       unsigned long id1, id2;
        unsigned long ret;
-
-       id1=(unsigned long)((const APP_INFO *)a_void)->thread_id;
-       id2=(unsigned long)((const APP_INFO *)a_void)->thread_idptr;
-       ret = id1 + id2;
-
+       ret = CRYPTO_THREADID_hash(&((const APP_INFO *)a_void)->threadid);
        ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
        return(ret);
        }
@@ -364,8 +355,7 @@ static APP_INFO *pop_info(void)
 
        if (amih != NULL)
                {
-               tmp.thread_id=CRYPTO_thread_id();
-               tmp.thread_idptr=CRYPTO_thread_idptr();
+               CRYPTO_THREADID_set(&tmp.threadid);
                if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
                        {
                        APP_INFO *next=ret->next;
@@ -376,10 +366,11 @@ static APP_INFO *pop_info(void)
                                lh_insert(amih,(char *)next);
                                }
 #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",
-                                       ret->thread_id, ret->thread_idptr, tmp.thread_id, tmp.thread_idptr);
+                               fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
+                                       CRYPTO_THREADID_hash(&ret->threadid),
+                                       CRYPTO_THREADID_hash(&tmp.threadid));
                                abort();
                                }
 #endif
@@ -419,8 +410,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
                                }
                        }
 
-               ami->thread_id=CRYPTO_thread_id();
-               ami->thread_idptr=CRYPTO_thread_idptr();
+               CRYPTO_THREADID_set(&ami->threadid);
                ami->file=file;
                ami->line=line;
                ami->info=info;
@@ -430,10 +420,11 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
                if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
                        {
 #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",
-                                       amim->thread_id, amim->thread_idptr, ami->thread_id, ami->thread_idptr);
+                               fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
+                                       CRYPTO_THREADID_hash(&amim->threadid),
+                                       CRYPTO_THREADID_hash(&ami->threadid));
                                abort();
                                }
 #endif
@@ -518,16 +509,7 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
                        m->file=file;
                        m->line=line;
                        m->num=num;
-                       if (options & V_CRYPTO_MDEBUG_THREAD)
-                               {
-                               m->thread_id=CRYPTO_thread_id();
-                               m->thread_idptr=CRYPTO_thread_idptr();
-                               }
-                       else
-                               {
-                               m->thread_id=0;
-                               m->thread_idptr=NULL;
-                               }
+                       CRYPTO_THREADID_set(&m->threadid);
 
                        if (order == break_order_num)
                                {
@@ -546,8 +528,7 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
                        else
                                m->time=0;
 
-                       tmp.thread_id=CRYPTO_thread_id();
-                       tmp.thread_idptr=CRYPTO_thread_idptr();
+                       CRYPTO_THREADID_set(&m->threadid);
                        m->app_info=NULL;
                        if (amih != NULL
                                && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
@@ -676,8 +657,7 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
        APP_INFO *amip;
        int ami_cnt;
        struct tm *lcl = NULL;
-       unsigned long ti;
-       void *tip;
+       CRYPTO_THREADID tid;
 
 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
 
@@ -699,7 +679,8 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
 
        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);
                }
 
@@ -716,8 +697,7 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
        ami_cnt=0;
        if (!amip)
                return;
-       ti=amip->thread_id;
-       tip=amip->thread_idptr;
+       CRYPTO_THREADID_set(&tid);
        
        do
                {
@@ -727,8 +707,8 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
                ami_cnt++;
                memset(buf,'>',ami_cnt);
                BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
-                       " thread=%lu/%p, file=%s, line=%d, info=\"",
-                       amip->thread_id, amip->thread_idptr, amip->file, amip->line);
+                       " thread=%lu, file=%s, line=%d, info=\"",
+                       CRYPTO_THREADID_hash(&amip->threadid), amip->file, amip->line);
                buf_len=strlen(buf);
                info_len=strlen(amip->info);
                if (128 - buf_len - 3 < info_len)
@@ -748,8 +728,8 @@ static void print_leak(const MEM *m, MEM_LEAK *l)
 
                amip = amip->next;
                }
-       while(amip && amip->thread_id == ti && amip->thread_idptr == tip);
-               
+       while(amip && !CRYPTO_THREADID_cmp(&amip->threadid, &tid));
+
 #ifdef LEVITTE_DEBUG_MEM
        if (amip)
                {
index cfc7877..59535b9 100644 (file)
@@ -145,8 +145,7 @@ static unsigned int crypto_lock_rand = 0; /* may be set only when a thread
                                            * holds CRYPTO_LOCK_RAND
                                            * (to prevent double locking) */
 /* 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 void *locking_thread_idptr = NULL; /* valid iff crypto_lock_rand is set */
+static CRYPTO_THREADID locking_tid;
 
 
 #ifdef PREDICT
@@ -214,8 +213,10 @@ static void ssleay_rand_add(const void *buf, int num, double add)
        /* check if we already have the lock */
        if (crypto_lock_rand)
                {
+               CRYPTO_THREADID tid;
+               CRYPTO_THREADID_set(&tid);
                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_tid, &tid);
                CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
                }
        else
@@ -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 */
        CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
-       locking_thread_id = CRYPTO_thread_id();
-       locking_thread_idptr = CRYPTO_thread_idptr();
+       CRYPTO_THREADID_set(&locking_tid);
        CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
        crypto_lock_rand = 1;
 
@@ -536,8 +536,10 @@ static int ssleay_rand_status(void)
         * (could happen if a RAND_poll() implementation calls RAND_status()) */
        if (crypto_lock_rand)
                {
+               CRYPTO_THREADID tid;
+               CRYPTO_THREADID_set(&tid);
                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_tid, &tid);
                CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
                }
        else
@@ -549,8 +551,7 @@ static int ssleay_rand_status(void)
                
                /* prevent ssleay_rand_bytes() from trying to obtain the lock again */
                CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
-               locking_thread_id = CRYPTO_thread_id();
-               locking_thread_idptr = CRYPTO_thread_idptr();
+               CRYPTO_THREADID_set(&locking_tid);
                CRYPTO_w_unlock(CRYPTO_LOCK_RAND2);
                crypto_lock_rand = 1;
                }
index a1ecd6d..7f58a89 100644 (file)
@@ -263,8 +263,10 @@ err:
 static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
 {
        BN_BLINDING *ret;
+       CRYPTO_THREADID tid;
        int got_write_lock = 0;
 
+       CRYPTO_THREADID_set(&tid);
        CRYPTO_r_lock(CRYPTO_LOCK_RSA);
 
        if (rsa->blinding == NULL)
@@ -281,7 +283,7 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
        if (ret == NULL)
                goto err;
 
-       if ((BN_BLINDING_get_thread_id(ret) == CRYPTO_thread_id()) && (BN_BLINDING_get_thread_idptr(ret) == CRYPTO_thread_idptr()))
+       if (!BN_BLINDING_cmp_thread(ret, &tid))
                {
                /* rsa->blinding is ours! */
 
index dd09609..cf35c0d 100644 (file)
@@ -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);
                goto err;
                }
-       BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id());
-       BN_BLINDING_set_thread_idptr(ret, CRYPTO_thread_idptr());
+       BN_BLINDING_set_thread(ret);
 err:
        BN_CTX_end(ctx);
        if (in_ctx == NULL)
index 4080de8..c8705a0 100644 (file)
@@ -328,7 +328,7 @@ int main(int argc, char *argv[])
        }
 
     CRYPTO_cleanup_all_ex_data();
-    ERR_remove_state(0);
+    ERR_remove_thread_state(NULL);
 
     CRYPTO_mem_leaks_fp(stderr);
 
index 7b087f7..fbb5be7 100644 (file)
@@ -4,7 +4,7 @@
 
 BN_BLINDING_new, BN_BLINDING_free, BN_BLINDING_update, BN_BLINDING_convert, 
 BN_BLINDING_invert, BN_BLINDING_convert_ex, BN_BLINDING_invert_ex, 
-BN_BLINDING_get_thread_id, BN_BLINDING_set_thread_id, BN_BLINDING_get_flags,
+BN_BLINDING_set_thread, BN_BLINDING_cmp_thread, BN_BLINDING_get_flags,
 BN_BLINDING_set_flags, BN_BLINDING_create_param - blinding related BIGNUM
 functions.
 
@@ -22,8 +22,10 @@ functions.
        BN_CTX *ctx);
  int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
        BN_CTX *ctx);
- 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(BN_BLINDING *);
+ int BN_BLINDING_cmp_thread(const BN_BLINDING *,
+        const CRYPTO_THREADID *);
  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,
@@ -54,11 +56,10 @@ BN_BLINDING_convert() and BN_BLINDING_invert() are wrapper
 functions for BN_BLINDING_convert_ex() and BN_BLINDING_invert_ex()
 with B<r> set to NULL.
 
-BN_BLINDING_set_thread_id() and BN_BLINDING_get_thread_id()
-set and get the "thread id" value of the B<BN_BLINDING> structure,
-a field provided to users of B<BN_BLINDING> structure to help them
-provide proper locking if needed for multi-threaded use. The 
-"thread id" of a newly allocated B<BN_BLINDING> structure is zero.
+BN_BLINDING_set_thread() and BN_BLINDING_cmp_thread()
+set and compare the "thread id" of the B<BN_BLINDING> structure,
+allowing users of the B<BN_BLINDING> structure to
+provide proper locking if needed for multi-threaded use.
 
 BN_BLINDING_get_flags() returns the BN_BLINDING flags. Currently
 there are two supported flags: B<BN_BLINDING_NO_UPDATE> and
@@ -85,6 +86,12 @@ success and 0 if an error occured.
 
 BN_BLINDING_get_thread_id() returns the thread id (a B<unsigned long>
 value) or 0 if not set.
+BN_BLINDING_cmp_thread() returns 0 if the thread id associated with the
+B<BN_BLINDING> structure equals the provided thread id (which can be
+obtained by CRYPTO_THREADID_set()), otherwise it returns -1 or +1
+to indicate the thread ids are different (if the target architecture
+supports ordering of thread ids, this follows the traditional "cmp"
+semantics of memcmp() or strcmp()).
 
 BN_BLINDING_get_flags() returns the currently set B<BN_BLINDING> flags
 (a B<unsigned long> value).
@@ -102,6 +109,14 @@ 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
 and BN_BLINDING_create_param were first introduced in OpenSSL 0.9.8
 
+BN_BLINDING_get_thread_idptr, BN_BLINDING_set_thread_idptr were first
+introduced in OpenSSL 0.9.9
+
+BN_BLINDING_get_thread_id, BN_BLINDING_set_thread_id,
+BN_BLINDING_get_thread_idptr, BN_BLINDING_set_thread_idptr were all
+deprecated in favour of BN_BLINDING_set_thread, BN_BLINDING_cmp_thread
+which were introduced in OpenSSL 0.9.9
+
 =head1 AUTHOR
 
 Nils Larsch for the OpenSSL project (http://www.openssl.org).
index cd2f8e5..213cba1 100644 (file)
@@ -131,8 +131,10 @@ bn - multiprecision integer arithmetics
        BN_CTX *ctx);
  int BN_BLINDING_invert_ex(BIGNUM *n,const BIGNUM *r,BN_BLINDING *b,
        BN_CTX *ctx);
- 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(BN_BLINDING *);
+ int BN_BLINDING_cmp_thread(const BN_BLINDING *,
+        const CRYPTO_THREADID *);
+
  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,
index 230cbe8..76bd10c 100644 (file)
@@ -76,9 +76,7 @@ below).
 
 idptr_function(void) is a function that similarly returns a thread ID,
 but of type void *.  This is not needed on platforms where &errno is
-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
-suffices to define one of these two callback functions appropriately.
+different for each thread.
 
 Additionally, OpenSSL supports dynamic locks, and sometimes, some parts
 of OpenSSL need it for better performance.  To enable this, the following
@@ -166,7 +164,9 @@ 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.)
+this object.) Note that if neither id_function() or idptr_function()
+are provided, OpenSSL will use (&errno) as a fallback (as this
+usually returns a unique address for each thread).
 
 =head1 EXAMPLES
 
index 83a571d..b20ab0f 100644 (file)
@@ -1014,7 +1014,7 @@ end:
 #endif
        CRYPTO_cleanup_all_ex_data();
        ERR_free_strings();
-       ERR_remove_state(0);
+       ERR_remove_thread_state(NULL);
        EVP_cleanup();
        CRYPTO_mem_leaks(bio_err);
        if (bio_err != NULL) BIO_free(bio_err);