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.
#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.
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);
}
/*
void cryptoint_cleanup_library (void)
{
- assert (initialized);
-
- krb5int_prng_cleanup ();
-
- initialized = 0;
+ if (!INITIALIZER_RAN(cryptoint_initialize_library))
+ return;
+ krb5int_prng_cleanup ();
}
#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.
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);
void krb5int_prng_cleanup (void)
{
- if (inited) krb5int_yarrow_final (&y_ctx);
- inited = 0;
+ if (inited)
+ krb5int_yarrow_final (&y_ctx);
+ inited = 0;
}