diff options
Diffstat (limited to 'lib/krb5/crypto-rand.c')
-rw-r--r-- | lib/krb5/crypto-rand.c | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/lib/krb5/crypto-rand.c b/lib/krb5/crypto-rand.c index 49bd67936259..7b126c6958c4 100644 --- a/lib/krb5/crypto-rand.c +++ b/lib/krb5/crypto-rand.c @@ -33,6 +33,9 @@ #include "krb5_locl.h" +#undef HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE +#define HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE + #define ENTROPY_NEEDED 128 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -40,6 +43,7 @@ static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; static int seed_something(void) { +#ifndef NO_RANDFILE char buf[1024], seedfile[256]; /* If there is a seed file, load it. But such a file cannot be trusted, @@ -58,52 +62,91 @@ seed_something(void) seedfile[0] = '\0'; } else seedfile[0] = '\0'; +#endif /* Calling RAND_status() will try to use /dev/urandom if it exists so we do not have to deal with it. */ if (RAND_status() != 1) { -#ifndef _WIN32 - krb5_context context; - const char *p; - - /* Try using egd */ - if (!krb5_init_context(&context)) { - p = krb5_config_get_string(context, NULL, "libdefaults", - "egd_socket", NULL); - if (p != NULL) - RAND_egd_bytes(p, ENTROPY_NEEDED); - krb5_free_context(context); - } -#else /* TODO: Once a Windows CryptoAPI RAND method is defined, we can use that and failover to another method. */ -#endif } if (RAND_status() == 1) { +#ifndef NO_RANDFILE /* Update the seed file */ if (seedfile[0]) RAND_write_file(seedfile); +#endif return 0; } else return -1; } -KRB5_LIB_FUNCTION void KRB5_LIB_CALL -krb5_generate_random_block(void *buf, size_t len) +/** + * Fill buffer buf with len bytes of PRNG randomness that is ok to use + * for key generation, padding and public diclosing the randomness w/o + * disclosing the randomness source. + * + * This function can fail, and callers must check the return value. + * + * @param buf a buffer to fill with randomness + * @param len length of memory that buf points to. + * + * @return return 0 on success or HEIM_ERR_RANDOM_OFFLINE if the + * funcation failed to initialize the randomness source. + * + * @ingroup krb5_crypto + */ + +HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_generate_random(void *buf, size_t len) { static int rng_initialized = 0; + int ret; HEIMDAL_MUTEX_lock(&crypto_mutex); if (!rng_initialized) { - if (seed_something()) - krb5_abortx(NULL, "Fatal: could not seed the " - "random number generator"); - + if (seed_something()) { + HEIMDAL_MUTEX_unlock(&crypto_mutex); + return HEIM_ERR_RANDOM_OFFLINE; + } rng_initialized = 1; } - HEIMDAL_MUTEX_unlock(&crypto_mutex); if (RAND_bytes(buf, len) <= 0) + ret = HEIM_ERR_RANDOM_OFFLINE; + else + ret = 0; + HEIMDAL_MUTEX_unlock(&crypto_mutex); + + return ret; +} + +/** + * Fill buffer buf with len bytes of PRNG randomness that is ok to use + * for key generation, padding and public diclosing the randomness w/o + * disclosing the randomness source. + * + * This function can NOT fail, instead it will abort() and program will crash. + * + * If this function is called after a successful krb5_init_context(), + * the chance of it failing is low due to that krb5_init_context() + * pulls out some random, and quite commonly the randomness sources + * will not fail once it have started to produce good output, + * /dev/urandom behavies that way. + * + * @param buf a buffer to fill with randomness + * @param len length of memory that buf points to. + * + * @ingroup krb5_crypto + */ + + +KRB5_LIB_FUNCTION void KRB5_LIB_CALL +krb5_generate_random_block(void *buf, size_t len) +{ + int ret = krb5_generate_random(buf, len); + if (ret) krb5_abortx(NULL, "Failed to generate random block"); } |