Add a mutex for the shared static storage used by Yarrow
authorKen Raeburn <raeburn@mit.edu>
Sat, 1 May 2004 00:00:02 +0000 (00:00 +0000)
committerKen Raeburn <raeburn@mit.edu>
Sat, 1 May 2004 00:00:02 +0000 (00:00 +0000)
* crypto_libinit.c (initialized): Variable deleted.
(cryptoint_initialize_library, cryptoint_cleanup_library): Use new macros for
automatic shared library init/fini functions.
(prng_cleanup): Declaration deleted.
(krb5int_prng_init, krb5int_prng_cleanup): Declare.
(cryptoint_initialize_library): Call krb5int_prng_init.
(krb5int_crypto_init): New function, checks that cryptoint_initialize_library
was called successfully.
(cryptoint_cleanup_library): Call krb5int_prng_cleanup only if the initializer
ran.
* crypto_libinit.h: Deleted.
* prng.c: Include k5-thread.h.
(init_once, init_error, yarrow_lock): New variables.
(krb5int_prng_init): New function; finish initializing the mutex lock.
(do_yarrow_init): New function.
(krb5_c_random_add_entropy): Call it once only.  Lock the mutex before
processing the input.
(krb5_c_random_make_octets): Lock the mutex before extracting random bytes.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16290 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/ChangeLog
src/lib/crypto/crypto_libinit.c
src/lib/crypto/crypto_libinit.h [deleted file]
src/lib/crypto/prng.c

index e792bf43065d96cca7683a1aff0ec5bdeab2467a..7916871df1f15e9bd8c1a4dbb5093ad2ab91d63c 100644 (file)
@@ -1,5 +1,26 @@
 2004-04-30  Ken Raeburn  <raeburn@mit.edu>
 
+       * crypto_libinit.c (initialized): Variable deleted.
+       (cryptoint_initialize_library, cryptoint_cleanup_library): Use new
+       macros for automatic shared library init/fini functions.
+       (prng_cleanup): Declaration deleted.
+       (krb5int_prng_init, krb5int_prng_cleanup): Declare.
+       (cryptoint_initialize_library): Call krb5int_prng_init.
+       (krb5int_crypto_init): New function, checks that
+       cryptoint_initialize_library was called successfully.
+       (cryptoint_cleanup_library): Call krb5int_prng_cleanup only if the
+       initializer ran.
+       * crypto_libinit.h: Deleted.
+       * prng.c: Include k5-thread.h.
+       (init_once, init_error, yarrow_lock): New variables.
+       (krb5int_prng_init): New function; finish initializing the mutex
+       lock.
+       (do_yarrow_init): New function.
+       (krb5_c_random_add_entropy): Call it once only.  Lock the mutex
+       before processing the input.
+       (krb5_c_random_make_octets): Lock the mutex before extracting
+       random bytes.
+
        * libk5crypto.exports: Drop the library init/fini functions and
        the DES tables from the export list.
 
index a799b1ec3d42fb3be545548e0cd6af8b87ca5457..91bf8ac220f625e82a3427913eba43d0e3d54c9e 100644 (file)
@@ -1,11 +1,11 @@
 #include <assert.h>
-#include "crypto_libinit.h"
-/* get prng_cleanup decl */
 #include "k5-int.h"
 
-static int             initialized = 0;
+MAKE_INIT_FUNCTION(cryptoint_initialize_library);
+MAKE_FINI_FUNCTION(cryptoint_cleanup_library);
 
-extern void prng_cleanup (void);
+extern int krb5int_prng_init(void);
+extern void krb5int_prng_cleanup (void);
 
 /*
  * Initialize the crypto library.
@@ -13,12 +13,12 @@ extern void prng_cleanup (void);
 
 int cryptoint_initialize_library (void)
 {
-       
-       if (!initialized) {
-               initialized = 1;
-       }
-       
-       return 0;
+    return krb5int_prng_init();
+}
+
+int krb5int_crypto_init(void)
+{
+    return CALL_INIT_FUNCTION(cryptoint_initialize_library);
 }
 
 /*
@@ -27,9 +27,7 @@ int cryptoint_initialize_library (void)
 
 void cryptoint_cleanup_library (void)
 {
-       assert (initialized);
-       
-       krb5int_prng_cleanup ();
-       
-       initialized = 0;
+    if (!INITIALIZER_RAN(cryptoint_initialize_library))
+       return;
+    krb5int_prng_cleanup ();
 }
diff --git a/src/lib/crypto/crypto_libinit.h b/src/lib/crypto/crypto_libinit.h
deleted file mode 100644 (file)
index 44c7e16..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef K5CRYPTO_LIBINIT_H
-#define K5CRYPTO_LIBINIT_H
-
-int cryptoint_initialize_library (void);
-void cryptoint_cleanup_library (void);
-
-#endif /* K5CRYPTO_LIBINIT_H */
index eebaca2b9a060a0e6fd864d6e13e426fbe347e3a..dd1c4c852191d76235c5e877619e9a17f5626ac3 100644 (file)
 #include "k5-int.h"
 #include "enc_provider.h"
 #include <assert.h>
+#include "k5-thread.h"
 
 #include "yarrow.h"
 static Yarrow_CTX y_ctx;
-static int inited=0;
+static k5_once_t init_once = K5_ONCE_INIT;
+static int inited, init_error;
+static k5_mutex_t yarrow_lock = K5_MUTEX_PARTIAL_INITIALIZER;
 
 /* Helper function to estimate entropy based on sample length
  * and where it comes from.
@@ -54,56 +57,85 @@ entropy_estimate (unsigned int randsource, size_t length)
 return (0);
 }
 
-krb5_error_code KRB5_CALLCONV
-krb5_c_random_add_entropy (krb5_context context, unsigned int randsource,
-                          const krb5_data *data)
+int krb5int_prng_init(void)
 {
-  int yerr;
+    return k5_mutex_finish_init(&yarrow_lock);
+}
 
-  if (inited == 0) {
+static void do_yarrow_init(void)
+{
     unsigned i;
+    int yerr;
+
     yerr = krb5int_yarrow_init (&y_ctx, NULL);
-    if ((yerr != YARROW_OK) && (yerr != YARROW_NOT_SEEDED))
-      return (KRB5_CRYPTO_INTERNAL);
-      
+    if ((yerr != YARROW_OK) && (yerr != YARROW_NOT_SEEDED)) {
+       init_error = yerr;
+       return;
+    }
 
     for (i=0; i < KRB5_C_RANDSOURCE_MAX; i++ ) {
-      unsigned  source_id;
-      if (krb5int_yarrow_new_source (&y_ctx, &source_id) != YARROW_OK )
-       return KRB5_CRYPTO_INTERNAL;
-      assert (source_id == i);
+       unsigned source_id;
+       if (krb5int_yarrow_new_source (&y_ctx, &source_id) != YARROW_OK ) {
+           init_error = 17;
+           return;
+       }
+       assert (source_id == i);
     }
     inited=1;
-      
-  }
+    init_error = 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_add_entropy (krb5_context context, unsigned int randsource,
+                          const krb5_data *data)
+{
+  int yerr;
+
+  /* Make sure the mutex got initialized.  */
+  yerr = krb5int_crypto_init();
+  if (yerr)
+      return yerr;
+  /* Run the Yarrow init code, if not done already.  */
+  yerr = k5_once(&init_once, do_yarrow_init);
+  if (yerr)
+      return yerr;
+  /* Return an error if the Yarrow initialization failed.  */
+  if (init_error)
+      return KRB5_CRYPTO_INTERNAL;
+  /* Now, finally, feed in the data.  */
+  yerr = k5_mutex_lock(&yarrow_lock);
+  if (yerr)
+      return yerr;
   yerr = krb5int_yarrow_input (&y_ctx, randsource,
                               data->data, data->length,
                               entropy_estimate (randsource, data->length));
+  k5_mutex_unlock(&yarrow_lock);
   if (yerr != YARROW_OK)
     return (KRB5_CRYPTO_INTERNAL);
   return (0);
 }
 
 krb5_error_code KRB5_CALLCONV
-krb5_c_random_seed
-(krb5_context context, krb5_data *data)
+krb5_c_random_seed (krb5_context context, krb5_data *data)
 {
-  return (krb5_c_random_add_entropy (context,  KRB5_C_RANDSOURCE_OLDAPI, data));
+    return krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_OLDAPI, data);
 }
 
-
-
 krb5_error_code KRB5_CALLCONV
 krb5_c_random_make_octets(krb5_context context, krb5_data *data)
 {
     int yerr;
     assert (inited);
+    yerr = k5_mutex_lock(&yarrow_lock);
+    if (yerr)
+       return yerr;
     yerr = krb5int_yarrow_output (&y_ctx, data->data, data->length);
     if (yerr == YARROW_NOT_SEEDED) {
       yerr = krb5int_yarrow_reseed (&y_ctx, YARROW_SLOW_POOL);
       if (yerr == YARROW_OK)
        yerr = krb5int_yarrow_output (&y_ctx, data->data, data->length);
     }
+    k5_mutex_unlock(&yarrow_lock);
     if ( yerr != YARROW_OK)
       return (KRB5_CRYPTO_INTERNAL);
     return(0);
@@ -111,8 +143,9 @@ krb5_c_random_make_octets(krb5_context context, krb5_data *data)
 
 void krb5int_prng_cleanup (void)
 {
-  if (inited) krb5int_yarrow_final (&y_ctx);
-       inited = 0;
+    if (inited)
+       krb5int_yarrow_final (&y_ctx);
+    inited = 0;
 }