From 516c12c9a976ec8f0956d22370e7a5b6834ba1fd Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Mon, 21 Oct 2013 08:22:02 -0700 Subject: [PATCH] intruduce krb5_generate_random() that can fail and return an error, check for it at krb5_context creation time --- include/bits.c | 30 +++++++++++++++++++------ include/krb5-types.cross | 5 +++++ lib/krb5/context.c | 9 ++++++++ lib/krb5/crypto-rand.c | 57 +++++++++++++++++++++++++++++++++++++++++++----- lib/krb5/heim_err.et | 1 + 5 files changed, 89 insertions(+), 13 deletions(-) diff --git a/include/bits.c b/include/bits.c index 7e76828b4..2dea356f5 100644 --- a/include/bits.c +++ b/include/bits.c @@ -255,39 +255,55 @@ int main(int argc, char **argv) #endif /* KRB5 */ + fprintf(f, "#if !defined(__has_extension)\n"); + fprintf(f, "#define __has_extension(x) 0\n"); + fprintf(f, "#endif\n\n"); + + fprintf(f, "#ifndef KRB5TYPES_REQUIRE_GNUC\n"); + fprintf(f, "#define KRB5TYPES_REQUIRE_GNUC(m,n,p) \\\n"); + fprintf(f, " (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) >= \\\n"); + fprintf(f, " (((m) * 10000) + ((n) * 100) + (p)))\n"); + fprintf(f, "#endif\n\n"); + fprintf(f, "#ifndef HEIMDAL_DEPRECATED\n"); - fprintf(f, "#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n"); + fprintf(f, "#if __has_extension(deprecated) || KRB5TYPES_REQUIRE_GNUC(3,1,0)\n"); fprintf(f, "#define HEIMDAL_DEPRECATED __attribute__((deprecated))\n"); fprintf(f, "#elif defined(_MSC_VER) && (_MSC_VER>1200)\n"); fprintf(f, "#define HEIMDAL_DEPRECATED __declspec(deprecated)\n"); fprintf(f, "#else\n"); fprintf(f, "#define HEIMDAL_DEPRECATED\n"); fprintf(f, "#endif\n"); - fprintf(f, "#endif\n"); + fprintf(f, "#endif\n\n"); fprintf(f, "#ifndef HEIMDAL_PRINTF_ATTRIBUTE\n"); - fprintf(f, "#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n"); + fprintf(f, "#if __has_extension(format) || KRB5TYPES_REQUIRE_GNUC(3,1,0)\n"); fprintf(f, "#define HEIMDAL_PRINTF_ATTRIBUTE(x) __attribute__((format x))\n"); fprintf(f, "#else\n"); fprintf(f, "#define HEIMDAL_PRINTF_ATTRIBUTE(x)\n"); fprintf(f, "#endif\n"); - fprintf(f, "#endif\n"); + fprintf(f, "#endif\n\n"); fprintf(f, "#ifndef HEIMDAL_NORETURN_ATTRIBUTE\n"); - fprintf(f, "#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n"); + fprintf(f, "#if __has_extension(noreturn) || KRB5TYPES_REQUIRE_GNUC(3,1,0)\n"); fprintf(f, "#define HEIMDAL_NORETURN_ATTRIBUTE __attribute__((noreturn))\n"); fprintf(f, "#else\n"); fprintf(f, "#define HEIMDAL_NORETURN_ATTRIBUTE\n"); fprintf(f, "#endif\n"); - fprintf(f, "#endif\n"); + fprintf(f, "#endif\n\n"); fprintf(f, "#ifndef HEIMDAL_UNUSED_ATTRIBUTE\n"); - fprintf(f, "#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1 )))\n"); + fprintf(f, "#if __has_extension(unused) || KRB5TYPES_REQUIRE_GNUC(3,1,0)\n"); fprintf(f, "#define HEIMDAL_UNUSED_ATTRIBUTE __attribute__((unused))\n"); fprintf(f, "#else\n"); fprintf(f, "#define HEIMDAL_UNUSED_ATTRIBUTE\n"); fprintf(f, "#endif\n"); + fprintf(f, "#endif\n\n"); + + fprintf(f, "#ifndef HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE\n"); + fprintf(f, "#if __has_extension(warn_unused_result) || KRB5TYPES_REQUIRE_GNUC(3,3,0)\n"); + fprintf(f, "#define HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE __attribute__((warn_unused_result))\n"); fprintf(f, "#endif\n"); + fprintf(f, "#endif\n\n"); fprintf(f, "#endif /* %s */\n", hb); diff --git a/include/krb5-types.cross b/include/krb5-types.cross index ee43abd4a..2d9d1dced 100644 --- a/include/krb5-types.cross +++ b/include/krb5-types.cross @@ -56,6 +56,11 @@ typedef ssize_t krb5_ssize_t; #endif #endif +#ifndef HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE +#if __has_extension(__warn_unused_result__) || KRB5TYPES_REQUIRE_GNUC(3,3,0) +#define HEIMDAL_WARN_UNUSED_RESULT_ATTRIBUTE __attribute__((__warn_unused_result__)) +#endif + typedef int krb5_socket_t; #endif /* __krb5_types_h__ */ diff --git a/lib/krb5/context.c b/lib/krb5/context.c index f35adc324..179c4e8a1 100644 --- a/lib/krb5/context.c +++ b/lib/krb5/context.c @@ -97,6 +97,15 @@ init_context_from_config_file(krb5_context context) const char * tmp; char **s; krb5_enctype *tmptypes; + uint8_t rnd; + + /* + * Pick one random character to make sure our random-ness source + * is alive. + */ + ret = krb5_generate_random(&rnd, sizeof(rnd)); + if (ret) + return ret; INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout"); diff --git a/lib/krb5/crypto-rand.c b/lib/krb5/crypto-rand.c index 226009ca0..af22633e1 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; @@ -94,20 +97,62 @@ seed_something(void) 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"); - + 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. + * + * @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"); } diff --git a/lib/krb5/heim_err.et b/lib/krb5/heim_err.et index da2c4c111..69039bb4d 100644 --- a/lib/krb5/heim_err.et +++ b/lib/krb5/heim_err.et @@ -20,6 +20,7 @@ error_code SERVICE_NOMATCH, "Unacceptable service used" error_code NOT_SEEKABLE, "File descriptor not seekable" error_code TOO_BIG, "Offset too large" error_code BAD_HDBENT_ENCODING, "Invalid HDB entry encoding" +error_code RANDOM_OFFLINE, "No random source available" index 64 prefix HEIM_PKINIT -- 2.11.4.GIT