From 6a365f0740ff683de52751c1c2903b0ddb6a7e0c Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 15 Apr 2008 05:56:35 +0000 Subject: [PATCH] added API for random number generators, served through credential factory ported randomizer_t to a rng_t on top of /dev/(u)random (plugin random) --- configure.in | 13 ++ src/charon/daemon.c | 23 ++- .../encoding/payloads/encryption_payload.c | 28 ++-- src/charon/network/receiver.c | 21 ++- src/charon/plugins/eap_aka/eap_aka.c | 13 +- src/charon/plugins/eap_md5/eap_md5.c | 12 +- src/charon/plugins/eap_sim/eap_sim.c | 13 +- src/charon/plugins/stroke/stroke_cred.c | 6 +- src/charon/sa/ike_sa.h | 1 - src/charon/sa/ike_sa_manager.c | 18 ++- src/charon/sa/tasks/child_create.c | 13 +- src/charon/sa/tasks/ike_init.c | 27 ++-- src/charon/sa/tasks/ike_me.c | 28 ++-- src/charon/sa/tasks/ike_natd.c | 12 +- src/libfast/session.c | 15 +- src/libstrongswan/Makefile.am | 6 +- src/libstrongswan/chunk.c | 19 +-- src/libstrongswan/chunk.h | 4 +- src/libstrongswan/crypto/crypto_factory.c | 90 ++++++++++- src/libstrongswan/crypto/crypto_factory.h | 31 +++- src/libstrongswan/crypto/pkcs7.c | 23 ++- src/libstrongswan/crypto/rngs/rng.c | 24 +++ src/libstrongswan/crypto/rngs/rng.h | 75 +++++++++ .../plugins/gmp/gmp_diffie_hellman.c | 14 +- .../plugins/gmp/gmp_rsa_private_key.c | 49 +++--- src/libstrongswan/plugins/random/Makefile.am | 11 ++ .../plugins/random/random_plugin.c | 62 ++++++++ .../plugins/random/random_plugin.h | 47 ++++++ src/libstrongswan/plugins/random/random_rng.c | 134 ++++++++++++++++ src/libstrongswan/plugins/random/random_rng.h | 49 ++++++ .../plugins/x509/x509_ocsp_request.c | 19 ++- src/libstrongswan/utils/randomizer.c | 150 ------------------ src/libstrongswan/utils/randomizer.h | 101 ------------ 33 files changed, 700 insertions(+), 451 deletions(-) create mode 100644 src/libstrongswan/crypto/rngs/rng.c create mode 100644 src/libstrongswan/crypto/rngs/rng.h create mode 100644 src/libstrongswan/plugins/random/Makefile.am create mode 100644 src/libstrongswan/plugins/random/random_plugin.c create mode 100644 src/libstrongswan/plugins/random/random_plugin.h create mode 100644 src/libstrongswan/plugins/random/random_rng.c create mode 100644 src/libstrongswan/plugins/random/random_rng.h delete mode 100644 src/libstrongswan/utils/randomizer.c delete mode 100644 src/libstrongswan/utils/randomizer.h diff --git a/configure.in b/configure.in index 9e0de9cd4..f9824bbb2 100644 --- a/configure.in +++ b/configure.in @@ -223,6 +223,17 @@ AC_ARG_ENABLE( gmp=true ) +AC_ARG_ENABLE( + [random], + AS_HELP_STRING([--disable-random],[disable RNG implementation on top of /dev/(u)random. (default is NO).]), + [if test x$enableval = xyes; then + random=true + else + random=false + fi], + random=true +) + AC_ARG_ENABLE( [x509], AS_HELP_STRING([--disable-x509],[disable own X509 certificate implementation plugin. (default is NO).]), @@ -589,6 +600,7 @@ AM_CONDITIONAL(USE_SHA1, test x$sha1 = xtrue) AM_CONDITIONAL(USE_SHA2, test x$sha2 = xtrue) AM_CONDITIONAL(USE_FIPS_PRF, test x$fips_prf = xtrue) AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue) +AM_CONDITIONAL(USE_RANDOM, test x$random = xtrue) AM_CONDITIONAL(USE_X509, test x$x509 = xtrue) AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue) AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue) @@ -645,6 +657,7 @@ AC_OUTPUT( src/libstrongswan/plugins/sha2/Makefile src/libstrongswan/plugins/fips_prf/Makefile src/libstrongswan/plugins/gmp/Makefile + src/libstrongswan/plugins/random/Makefile src/libstrongswan/plugins/hmac/Makefile src/libstrongswan/plugins/x509/Makefile src/libstrongswan/plugins/curl/Makefile diff --git a/src/charon/daemon.c b/src/charon/daemon.c index e1e9a71e7..77a41b412 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -90,12 +90,6 @@ static void dbg_bus(int level, char *fmt, ...) charon->bus->vsignal(charon->bus, DBG_LIB, level, fmt, args); va_end(args); } -/** - * Logging hook for library logs before logging facility initiated - */ -static void dbg_silent(int level, char *fmt, ...) -{ -} /** * Logging hook for library logs, using stderr output @@ -104,11 +98,14 @@ static void dbg_stderr(int level, char *fmt, ...) { va_list args; - va_start(args, fmt); - fprintf(stderr, "00[LIB] "); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); + if (level <= 1) + { + va_start(args, fmt); + fprintf(stderr, "00[LIB] "); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + } } /** @@ -483,8 +480,8 @@ int main(int argc, char *argv[]) level_t levels[DBG_MAX]; int signal; - /* silence the library during initialization, as we have no bus yet */ - dbg = dbg_silent; + /* logging for library during initialization, as we have no bus yet */ + dbg = dbg_stderr; /* initialize library */ library_init(STRONGSWAN_CONF); diff --git a/src/charon/encoding/payloads/encryption_payload.c b/src/charon/encoding/payloads/encryption_payload.c index cdfda3d5e..b74cb0974 100644 --- a/src/charon/encoding/payloads/encryption_payload.c +++ b/src/charon/encoding/payloads/encryption_payload.c @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -322,7 +321,7 @@ static void generate(private_encryption_payload_t *this) static status_t encrypt(private_encryption_payload_t *this) { chunk_t iv, padding, to_crypt, result; - randomizer_t *randomizer; + rng_t *rng; status_t status; size_t block_size; @@ -333,8 +332,12 @@ static status_t encrypt(private_encryption_payload_t *this) } /* for random data in iv and padding */ - randomizer = randomizer_create(); - + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) + { + DBG1(DBG_ENC, "could not encrypt, no RNG found"); + return FAILED; + } /* build payload chunk */ generate(this); @@ -344,12 +347,7 @@ static status_t encrypt(private_encryption_payload_t *this) /* build padding */ block_size = this->crypter->get_block_size(this->crypter); padding.len = block_size - ((this->decrypted.len + 1) % block_size); - status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding); - if (status != SUCCESS) - { - randomizer->destroy(randomizer); - return status; - } + rng->allocate_bytes(rng, padding.len, &padding); /* concatenate payload data, padding, padding len */ to_crypt.len = this->decrypted.len + padding.len + 1; @@ -361,14 +359,8 @@ static status_t encrypt(private_encryption_payload_t *this) /* build iv */ iv.len = block_size; - status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv); - randomizer->destroy(randomizer); - if (status != SUCCESS) - { - chunk_free(&to_crypt); - chunk_free(&padding); - return status; - } + rng->allocate_bytes(rng, iv.len, &iv); + rng->destroy(rng); DBG3(DBG_ENC, "data before encryption with padding %B", &to_crypt); diff --git a/src/charon/network/receiver.c b/src/charon/network/receiver.c index 2f3bf6cb2..a5415c806 100644 --- a/src/charon/network/receiver.c +++ b/src/charon/network/receiver.c @@ -88,9 +88,9 @@ struct private_receiver_t { u_int32_t secret_offset; /** - * the randomizer to use for secret generation + * the RNG to use for secret generation */ - randomizer_t *randomizer; + rng_t *rng; /** * hasher to use for cookie calculation @@ -304,8 +304,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) DBG1(DBG_NET, "generating new cookie secret after %d uses", this->secret_used); memcpy(this->secret_old, this->secret, SECRET_LENGTH); - this->randomizer->get_pseudo_random_bytes(this->randomizer, - SECRET_LENGTH, this->secret); + this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret); this->secret_switch = now; this->secret_used = 0; } @@ -333,7 +332,7 @@ static job_requeue_t receive_packets(private_receiver_t *this) static void destroy(private_receiver_t *this) { this->job->cancel(this->job); - this->randomizer->destroy(this->randomizer); + this->rng->destroy(this->rng); this->hasher->destroy(this->hasher); free(this); } @@ -355,12 +354,18 @@ receiver_t *receiver_create() free(this); return NULL; } - this->randomizer = randomizer_create(); + this->rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (this->rng == NULL) + { + DBG1(DBG_NET, "creating cookie RNG failed, no RNG supported"); + this->hasher->destroy(this->hasher); + free(this); + return NULL; + } this->secret_switch = now; this->secret_offset = random() % now; this->secret_used = 0; - this->randomizer->get_pseudo_random_bytes(this->randomizer, SECRET_LENGTH, - this->secret); + this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret); memcpy(this->secret_old, this->secret, SECRET_LENGTH); this->job = callback_job_create((callback_job_cb_t)receive_packets, diff --git a/src/charon/plugins/eap_aka/eap_aka.c b/src/charon/plugins/eap_aka/eap_aka.c index a8bef728e..570e9bfa4 100644 --- a/src/charon/plugins/eap_aka/eap_aka.c +++ b/src/charon/plugins/eap_aka/eap_aka.c @@ -45,7 +45,6 @@ #include #include -#include #include /* Use test vectors specified in S.S0055 @@ -835,7 +834,7 @@ static eap_payload_t *build_aka_payload(private_eap_aka_t *this, eap_code_t code static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, eap_payload_t **out) { - randomizer_t *randomizer; + rng_t *rng; status_t status; chunk_t mac, ak, autn; @@ -845,16 +844,16 @@ static status_t server_initiate_challenge(private_eap_aka_t *this, chunk_t sqn, chunk_free(&this->xres); /* generate RAND: - * we use our standard randomizer, not f0() proposed in S.S0055 + * we use a registered RNG, not f0() proposed in S.S0055 */ - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, RAND_LENGTH, &this->rand); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { DBG1(DBG_IKE, "generating RAND for EAP-AKA authentication failed"); return FAILED; } + rng->allocate_bytes(rng, RAND_LENGTH, &this->rand); + rng->destroy(rng); # ifdef TEST_VECTORS /* Test vector for RAND */ diff --git a/src/charon/plugins/eap_md5/eap_md5.c b/src/charon/plugins/eap_md5/eap_md5.c index 702042f37..7f41b2e18 100644 --- a/src/charon/plugins/eap_md5/eap_md5.c +++ b/src/charon/plugins/eap_md5/eap_md5.c @@ -122,18 +122,16 @@ static status_t initiate_peer(private_eap_md5_t *this, eap_payload_t **out) */ static status_t initiate_server(private_eap_md5_t *this, eap_payload_t **out) { - randomizer_t *randomizer; - status_t status; + rng_t *rng; eap_md5_header_t *req; - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, CHALLENGE_LEN, - &this->challenge); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { return FAILED; } + rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge); + rng->destroy(rng); req = alloca(PAYLOAD_LEN); req->length = htons(PAYLOAD_LEN); diff --git a/src/charon/plugins/eap_sim/eap_sim.c b/src/charon/plugins/eap_sim/eap_sim.c index 70651c91d..27c2c3a17 100644 --- a/src/charon/plugins/eap_sim/eap_sim.c +++ b/src/charon/plugins/eap_sim/eap_sim.c @@ -1037,7 +1037,7 @@ eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, identification_t *peer) { private_eap_sim_t *this; - randomizer_t *randomizer; + rng_t *rng; void *symbol; char *name; @@ -1098,16 +1098,15 @@ eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; this->alg = symbol; this->type = EAP_RESPONSE; - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, - &this->nonce)) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); - randomizer->destroy(randomizer); + DBG1(DBG_IKE, "unable to generate NONCE for EAP_SIM"); free(this); return NULL; } - randomizer->destroy(randomizer); + rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); + rng->destroy(rng); break; default: free(this); diff --git a/src/charon/plugins/stroke/stroke_cred.c b/src/charon/plugins/stroke/stroke_cred.c index e27800c50..4ac46abd2 100644 --- a/src/charon/plugins/stroke/stroke_cred.c +++ b/src/charon/plugins/stroke/stroke_cred.c @@ -574,7 +574,7 @@ static err_t extract_secret(chunk_t *secret, chunk_t *line) if (ugh != NULL) { - chunk_free_randomized(secret); + chunk_clear(secret); return ugh; } secret->len = len; @@ -702,7 +702,7 @@ static void load_secrets(private_stroke_cred_t *this) this->private->insert_last(this->private, key); } } - chunk_free_randomized(&secret); + chunk_clear(&secret); } else if ((match("PSK", &token) && (type = SHARED_IKE)) || (match("EAP", &token) && (type = SHARED_EAP)) || @@ -774,7 +774,7 @@ static void load_secrets(private_stroke_cred_t *this) } error: this->mutex->unlock(this->mutex); - chunk_free_randomized(&chunk); + chunk_clear(&chunk); } /** diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 1f0595c35..60e499d2c 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -38,7 +38,6 @@ typedef struct ike_sa_t ike_sa_t; #include #include #include -#include #include #include #include diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index b20cb2879..a8ce8725f 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -142,9 +142,9 @@ struct private_ike_sa_manager_t { linked_list_t *ike_sa_list; /** - * A randomizer, to get random SPIs for our side + * RNG to get random SPIs for our side */ - randomizer_t *randomizer; + rng_t *rng; /** * SHA1 hasher for IKE_SA_INIT retransmit detection @@ -304,8 +304,7 @@ static u_int64_t get_next_spi(private_ike_sa_manager_t *this) { u_int64_t spi; - this->randomizer->get_pseudo_random_bytes(this->randomizer, sizeof(spi), - (u_int8_t*)&spi); + this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi); return spi; } @@ -933,7 +932,7 @@ static void destroy(private_ike_sa_manager_t *this) this->ike_sa_list->destroy_function(this->ike_sa_list, (void*)entry_destroy); pthread_mutex_unlock(&(this->mutex)); - this->randomizer->destroy(this->randomizer); + this->rng->destroy(this->rng); this->hasher->destroy(this->hasher); free(this); @@ -968,9 +967,16 @@ ike_sa_manager_t *ike_sa_manager_create() free(this); return NULL; } + this->rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (this->rng == NULL) + { + DBG1(DBG_MGR, "manager initialization failed, no RNG supported"); + this->hasher->destroy(this->hasher); + free(this); + return NULL; + } this->ike_sa_list = linked_list_create(); pthread_mutex_init(&this->mutex, NULL); - this->randomizer = randomizer_create(); return &this->public; } diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index f4f814308..9dd5add8f 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -136,17 +136,16 @@ static status_t get_nonce(message_t *message, chunk_t *nonce) */ static status_t generate_nonce(chunk_t *nonce) { - status_t status; - randomizer_t *randomizer = randomizer_create(); + rng_t *rng; - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - nonce); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - DBG1(DBG_IKE, "error generating random nonce value"); + DBG1(DBG_IKE, "error generating nonce value, no RNG found"); return FAILED; } + rng->allocate_bytes(rng, NONCE_SIZE, nonce); + rng->destroy(rng); return SUCCESS; } diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index 84df19dc9..8cb706a26 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -218,8 +218,7 @@ static void process_payloads(private_ike_init_t *this, message_t *message) */ static status_t build_i(private_ike_init_t *this, message_t *message) { - randomizer_t *randomizer; - status_t status; + rng_t *rng; this->config = this->ike_sa->get_ike_cfg(this->ike_sa); SIG(IKE_UP_START, "initiating IKE_SA '%s' to %H", @@ -249,15 +248,14 @@ static status_t build_i(private_ike_init_t *this, message_t *message) /* generate nonce only when we are trying the first time */ if (this->my_nonce.ptr == NULL) { - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - &this->my_nonce); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - SIG(IKE_UP_FAILED, "error generating random nonce value"); + SIG(IKE_UP_FAILED, "error generating nonce"); return FAILED; } + rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); + rng->destroy(rng); } if (this->cookie.ptr) @@ -285,20 +283,21 @@ static status_t build_i(private_ike_init_t *this, message_t *message) */ static status_t process_r(private_ike_init_t *this, message_t *message) { - randomizer_t *randomizer; + rng_t *rng; this->config = this->ike_sa->get_ike_cfg(this->ike_sa); SIG(IKE_UP_START, "%H is initiating an IKE_SA", message->get_source(message)); this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING); - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, - &this->my_nonce) != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { - DBG1(DBG_IKE, "error generating random nonce value"); + DBG1(DBG_IKE, "error generating nonce"); + return FAILED; } - randomizer->destroy(randomizer); + rng->allocate_bytes(rng, NONCE_SIZE, &this->my_nonce); + rng->destroy(rng); #ifdef ME { diff --git a/src/charon/sa/tasks/ike_me.c b/src/charon/sa/tasks/ike_me.c index 58d99ea18..43bafaaf3 100644 --- a/src/charon/sa/tasks/ike_me.c +++ b/src/charon/sa/tasks/ike_me.c @@ -274,33 +274,25 @@ static status_t build_i(private_ike_me_t *this, message_t *message) case ME_CONNECT: { id_payload_t *id_payload; - randomizer_t *rand = randomizer_create(); + rng_t *rng; id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id); message->add_payload(message, (payload_t*)id_payload); + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (!rng) + { + DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT"); + return FAILED; + } if (!this->response) { /* only the initiator creates a connect ID. the responder returns * the connect ID that it received from the initiator */ - if (rand->allocate_pseudo_random_bytes(rand, - ME_CONNECTID_LEN, &this->connect_id) != SUCCESS) - { - DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT"); - rand->destroy(rand); - return FAILED; - } + rng->allocate_bytes(rng, ME_CONNECTID_LEN, &this->connect_id); } - - if (rand->allocate_pseudo_random_bytes(rand, - ME_CONNECTKEY_LEN, &this->connect_key) != SUCCESS) - { - DBG1(DBG_IKE, "unable to generate connect key for ME_CONNECT"); - rand->destroy(rand); - return FAILED; - } - - rand->destroy(rand); + rng->allocate_bytes(rng, ME_CONNECTKEY_LEN, &this->connect_key); + rng->destroy(rng); message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id); message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key); diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index e8daecdba..d72dd4504 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -113,17 +113,17 @@ static chunk_t generate_natd_hash(private_ike_natd_t *this, */ static chunk_t generate_natd_hash_faked(private_ike_natd_t *this) { - randomizer_t *randomizer; + rng_t *rng; chunk_t chunk; - randomizer = randomizer_create(); - if (randomizer->allocate_pseudo_random_bytes(randomizer, HASH_SIZE_SHA1, - &chunk) != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) { DBG1(DBG_IKE, "unable to get random bytes for NATD fake"); - chunk = chunk_empty; + return chunk_empty; } - randomizer->destroy(randomizer); + rng->allocate_bytes(rng, HASH_SIZE_SHA1, &chunk); + rng->destroy(rng); return chunk; } diff --git a/src/libfast/session.c b/src/libfast/session.c index 519187efa..87b7a266d 100644 --- a/src/libfast/session.c +++ b/src/libfast/session.c @@ -24,7 +24,6 @@ #include #include -#include typedef struct private_session_t private_session_t; @@ -82,12 +81,16 @@ static void create_sid(private_session_t *this, request_t *request) { char buf[16]; chunk_t chunk = chunk_from_buf(buf); - randomizer_t *randomizer = randomizer_create(); + rng_t *rng; - randomizer->get_pseudo_random_bytes(randomizer, sizeof(buf), buf); - this->sid = chunk_to_hex(chunk, FALSE); - request->add_cookie(request, "SID", this->sid); - randomizer->destroy(randomizer); + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (rng) + { + rng->get_bytes(rng, sizeof(buf), buf); + this->sid = chunk_to_hex(chunk, FALSE); + request->add_cookie(request, "SID", this->sid); + rng->destroy(rng); + } } /** diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index e192c859f..cb7e75039 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -23,6 +23,7 @@ crypto/crypters/crypter.c crypto/crypters/crypter.h \ crypto/hashers/hasher.h crypto/hashers/hasher.c \ crypto/pkcs9.c crypto/pkcs9.h \ crypto/prfs/prf.c crypto/prfs/prf.h \ +crypto/rngs/rng.c crypto/rngs/rng.h \ crypto/prf_plus.h crypto/prf_plus.c \ crypto/signers/signer.c crypto/signers/signer.h \ crypto/diffie_hellman.c crypto/diffie_hellman.h \ @@ -48,7 +49,6 @@ utils/lexparser.c utils/lexparser.h \ utils/linked_list.c utils/linked_list.h \ utils/enumerator.c utils/enumerator.h \ utils/optionsfrom.c utils/optionsfrom.h \ -utils/randomizer.c utils/randomizer.h \ utils/mutex.c utils/mutex.h \ plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h @@ -112,6 +112,10 @@ if USE_GMP SUBDIRS += plugins/gmp endif +if USE_RANDOM + SUBDIRS += plugins/random +endif + if USE_HMAC SUBDIRS += plugins/hmac endif diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c index 6f12c9b51..b2c9d600f 100644 --- a/src/libstrongswan/chunk.c +++ b/src/libstrongswan/chunk.c @@ -23,7 +23,6 @@ #include #include -#include /** * Empty chunk. @@ -285,22 +284,10 @@ void chunk_free(chunk_t *chunk) /** * Described in header. */ -void chunk_free_randomized(chunk_t *chunk) +void chunk_clear(chunk_t *chunk) { - if (chunk->ptr) - { - if (chunk->len > 0) - { - randomizer_t *randomizer = randomizer_create(); - - randomizer->get_pseudo_random_bytes(randomizer, - chunk->len, chunk->ptr); - randomizer->destroy(randomizer); - }; - free(chunk->ptr); - chunk->ptr = NULL; - } - chunk->len = 0; + memset(chunk->ptr, 0, chunk->len); + chunk_free(chunk); } /** diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h index 76acfde34..b4fd2f080 100644 --- a/src/libstrongswan/chunk.h +++ b/src/libstrongswan/chunk.h @@ -95,9 +95,9 @@ char *chunk_to_hex(chunk_t chunk, bool uppercase); void chunk_free(chunk_t *chunk); /** - * Overwrite the contents of a chunk with pseudo-random bytes and free them + * Overwrite the contents of a chunk and free it */ -void chunk_free_randomized(chunk_t *chunk); +void chunk_clear(chunk_t *chunk); /** * Initialize a chunk to point to buffer inspectable by sizeof() diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index 1bca84f2a..fc904f75d 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -52,6 +52,14 @@ struct prf_entry_t { prf_constructor_t create; }; +typedef struct rng_entry_t rng_entry_t; +struct rng_entry_t { + /** quality of randomness */ + rng_quality_t quality; + /** associated constructor */ + rng_constructor_t create; +}; + typedef struct dh_entry_t dh_entry_t; struct dh_entry_t { /** hash algorithm */ @@ -88,10 +96,15 @@ struct private_crypto_factory_t { linked_list_t *hashers; /** - * registered perfs, as prf_entry_t + * registered prfs, as prf_entry_t */ linked_list_t *prfs; + /** + * registered rngs, as rng_entry_t + */ + linked_list_t *rngs; + /** * registered diffie hellman, as dh_entry_t */ @@ -216,6 +229,39 @@ static prf_t* create_prf(private_crypto_factory_t *this, return prf; } +/** + * Implementation of crypto_factory_t.create_rng. + */ +static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) +{ + enumerator_t *enumerator; + rng_entry_t *entry; + u_int diff = ~0; + rng_constructor_t constr = NULL; + + this->mutex->lock(this->mutex); + enumerator = this->rngs->create_enumerator(this->rngs); + while (enumerator->enumerate(enumerator, &entry)) + { /* find the best matching quality, but at least as good as requested */ + if (entry->quality >= quality && diff > entry->quality - quality) + { + diff = entry->quality - quality; + constr = entry->create; + if (diff == 0) + { /* perfect match, won't get better */ + break; + } + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + if (constr) + { + return constr(quality); + } + return NULL; +} + /** * Implementation of crypto_factory_t.create_dh. */ @@ -396,6 +442,43 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) this->mutex->unlock(this->mutex); } +/** + * Implementation of crypto_factory_t.add_rng. + */ +static void add_rng(private_crypto_factory_t *this, rng_quality_t quality, + rng_constructor_t create) +{ + rng_entry_t *entry = malloc_thing(rng_entry_t); + + entry->quality = quality; + entry->create = create; + this->mutex->lock(this->mutex); + this->rngs->insert_last(this->rngs, entry); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of crypto_factory_t.remove_rng. + */ +static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) +{ + rng_entry_t *entry; + enumerator_t *enumerator; + + this->mutex->lock(this->mutex); + enumerator = this->rngs->create_enumerator(this->rngs); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->create == create) + { + this->rngs->remove_at(this->rngs, enumerator); + free(entry); + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + /** * Implementation of crypto_factory_t.add_dh. */ @@ -442,6 +525,7 @@ static void destroy(private_crypto_factory_t *this) this->signers->destroy_function(this->signers, free); this->hashers->destroy_function(this->hashers, free); this->prfs->destroy_function(this->prfs, free); + this->rngs->destroy_function(this->rngs, free); this->dhs->destroy_function(this->dhs, free); this->mutex->destroy(this->mutex); free(this); @@ -458,6 +542,7 @@ crypto_factory_t *crypto_factory_create() this->public.create_signer = (signer_t*(*)(crypto_factory_t*, integrity_algorithm_t))create_signer; this->public.create_hasher = (hasher_t*(*)(crypto_factory_t*, hash_algorithm_t))create_hasher; this->public.create_prf = (prf_t*(*)(crypto_factory_t*, pseudo_random_function_t))create_prf; + this->public.create_rng = (rng_t*(*)(crypto_factory_t*, rng_quality_t quality))create_rng; this->public.create_dh = (diffie_hellman_t*(*)(crypto_factory_t*, diffie_hellman_group_t group))create_dh; this->public.add_crypter = (void(*)(crypto_factory_t*, encryption_algorithm_t algo, crypter_constructor_t create))add_crypter; this->public.remove_crypter = (void(*)(crypto_factory_t*, crypter_constructor_t create))remove_crypter; @@ -467,6 +552,8 @@ crypto_factory_t *crypto_factory_create() this->public.remove_hasher = (void(*)(crypto_factory_t*, hasher_constructor_t create))remove_hasher; this->public.add_prf = (void(*)(crypto_factory_t*, pseudo_random_function_t algo, prf_constructor_t create))add_prf; this->public.remove_prf = (void(*)(crypto_factory_t*, prf_constructor_t create))remove_prf; + this->public.add_rng = (void(*)(crypto_factory_t*, rng_quality_t quality, rng_constructor_t create))add_rng; + this->public.remove_rng = (void(*)(crypto_factory_t*, rng_constructor_t create))remove_rng; this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh; this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh; this->public.destroy = (void(*)(crypto_factory_t*))destroy; @@ -475,6 +562,7 @@ crypto_factory_t *crypto_factory_create() this->signers = linked_list_create(); this->hashers = linked_list_create(); this->prfs = linked_list_create(); + this->rngs = linked_list_create(); this->dhs = linked_list_create(); this->mutex = mutex_create(MUTEX_RECURSIVE); diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h index c8c2bccc9..6bf070c31 100644 --- a/src/libstrongswan/crypto/crypto_factory.h +++ b/src/libstrongswan/crypto/crypto_factory.h @@ -28,6 +28,7 @@ typedef struct crypto_factory_t crypto_factory_t; #include #include #include +#include #include /** @@ -46,10 +47,15 @@ typedef signer_t* (*signer_constructor_t)(integrity_algorithm_t algo); typedef hasher_t* (*hasher_constructor_t)(hash_algorithm_t algo); /** - * Constructor function for pseudo random fucntions + * Constructor function for pseudo random functions */ typedef prf_t* (*prf_constructor_t)(pseudo_random_function_t algo); +/** + * Constructor function for source of randomness + */ +typedef rng_t* (*rng_constructor_t)(rng_quality_t quality); + /** * Constructor function for diffie hellman */ @@ -95,6 +101,14 @@ struct crypto_factory_t { */ prf_t* (*create_prf)(crypto_factory_t *this, pseudo_random_function_t algo); + /** + * Create a source of randomness. + * + * @param quality required randomness quality + * @return rng_t instance, NULL if no RNG with such a quality + */ + rng_t* (*create_rng)(crypto_factory_t *this, rng_quality_t quality); + /** * Create a diffie hellman instance. * @@ -175,6 +189,21 @@ struct crypto_factory_t { */ void (*remove_prf)(crypto_factory_t *this, prf_constructor_t create); + /** + * Register a source of randomness. + * + * @param quality quality of randomness this RNG serves + * @param create constructor function for such a quality + */ + void (*add_rng)(crypto_factory_t *this, rng_quality_t quality, rng_constructor_t create); + + /** + * Unregister a source of randomness. + * + * @param create constructor function to unregister + */ + void (*remove_rng)(crypto_factory_t *this, rng_constructor_t create); + /** * Register a diffie hellman constructor. * diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c index 662e8dd0d..13af6accc 100644 --- a/src/libstrongswan/crypto/pkcs7.c +++ b/src/libstrongswan/crypto/pkcs7.c @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id$ + * $Id: pkcs7.c 3488 2008-02-21 15:10:02Z martin $ */ #include @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "pkcs7.h" @@ -779,17 +778,17 @@ bool build_envelopedData(private_pkcs7_t *this, x509_t *cert, * and a pseudo-random iv */ { - randomizer_t *randomizer = randomizer_create(); - - randomizer->allocate_random_bytes(randomizer, - crypter->get_key_size(crypter), &symmetricKey); + rng_t *rng; + + rng = lib->crypto->create_rng(lib->crypto, RNG_REAL); + rng->allocate_bytes(rng, crypter->get_key_size(crypter), &symmetricKey); DBG4(" symmetric encryption key: %B", &symmetricKey); + rng->destroy(rng); - randomizer->allocate_pseudo_random_bytes(randomizer, - crypter->get_block_size(crypter), &iv); + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + rng->allocate_bytes(rng, crypter->get_block_size(crypter), &iv); DBG4(" initialization vector: %B", &iv); - - randomizer->destroy(randomizer); + rng->destroy(rng); } /* pad the data so that the total length becomes @@ -816,7 +815,7 @@ bool build_envelopedData(private_pkcs7_t *this, x509_t *cert, crypter->set_key(crypter, symmetricKey); crypter->encrypt(crypter, in, iv, &out); crypter->destroy(crypter); - chunk_free_randomized(&in); + chunk_clear(&in); DBG3(" encrypted data: %B", &out); /* build pkcs7 enveloped data object */ @@ -835,7 +834,7 @@ bool build_envelopedData(private_pkcs7_t *this, x509_t *cert, rsa_public_key_t *public_key = cert->get_public_key(cert); public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey); - chunk_free_randomized(&symmetricKey); + chunk_clear(&symmetricKey); encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey); diff --git a/src/libstrongswan/crypto/rngs/rng.c b/src/libstrongswan/crypto/rngs/rng.c new file mode 100644 index 000000000..435e043e8 --- /dev/null +++ b/src/libstrongswan/crypto/rngs/rng.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "rng.h" + +ENUM(rng_quality_names, RNG_WEAK, RNG_REAL, + "RNG_WEAK", + "RNG_STRONG", + "RNG_REAL", +); diff --git a/src/libstrongswan/crypto/rngs/rng.h b/src/libstrongswan/crypto/rngs/rng.h new file mode 100644 index 000000000..08f7af209 --- /dev/null +++ b/src/libstrongswan/crypto/rngs/rng.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: rng.h 3619 2008-03-19 14:02:52Z martin $ + */ + +/** + * @defgroup rng rng + * @{ @ingroup crypto + */ + +#ifndef RNG_H_ +#define RNG_H_ + +typedef enum rng_quality_t rng_quality_t; +typedef struct rng_t rng_t; + +#include + +/** + * Quality of generated random bytes. + */ +enum rng_quality_t { + /** weak randomness, usable for nonces, IVs */ + RNG_WEAK, + /** stronger randomness, usable for session keys */ + RNG_STRONG, + /** real random, key material */ + RNG_REAL, +}; + +/** + * enum name for rng_quality_t. + */ +extern enum_name_t *rng_quality_names; + +/** + * Generic interface for random number generators. + */ +struct rng_t { + + /** + * Generates random bytes and writes them in the buffer. + * + * @param len number of bytes to get + * @param buffer pointer where the generated bytes will be written + */ + void (*get_bytes) (rng_t *this, u_int len, u_int8_t *buffer); + + /** + * Generates random bytes and allocate space for them. + * + * @param len number of bytes to get + * @param chunk chunk which will hold generated bytes + */ + void (*allocate_bytes) (rng_t *this, u_int len, chunk_t *chunk); + + /** + * Destroys a rng object. + */ + void (*destroy) (rng_t *this); +}; + +#endif /*RNG_H_ @} */ diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c index 349ec419e..7f549ef95 100644 --- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c +++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c @@ -22,7 +22,6 @@ #include "gmp_diffie_hellman.h" -#include #include @@ -521,9 +520,8 @@ static void destroy(private_gmp_diffie_hellman_t *this) gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) { private_gmp_diffie_hellman_t *this = malloc_thing(private_gmp_diffie_hellman_t); - randomizer_t *randomizer; + rng_t *rng; chunk_t random; - status_t status; /* public functions */ this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; @@ -550,15 +548,15 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) destroy(this); return NULL; } - randomizer = randomizer_create(); - status = randomizer->allocate_pseudo_random_bytes( - randomizer, this->p_len, &random); - randomizer->destroy(randomizer); - if (status != SUCCESS) + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (!rng) { + DBG1("no RNG found for quality %N", rng_quality_names, RNG_STRONG); destroy(this); return NULL; } + rng->allocate_bytes(rng, this->p_len, &random); + rng->destroy(rng); mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr); chunk_free(&random); diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index c9928e6f4..8a4ee55ec 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -26,8 +26,6 @@ #include #include -#include -#include /** * Public exponent to use for key generation. @@ -151,23 +149,17 @@ bool gmp_rsa_public_key_build_id(mpz_t n, mpz_t e, identification_t **keyid, gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e); /** - * Auxiliary function overwriting private key material with - * pseudo-random bytes before releasing it + * Auxiliary function overwriting private key material with zero bytes */ static void mpz_clear_randomized(mpz_t z) { size_t len = mpz_size(z) * GMP_LIMB_BITS / BITS_PER_BYTE; - u_int8_t *random_bytes = alloca(len); - - randomizer_t *randomizer = randomizer_create(); + u_int8_t *random = alloca(len); - randomizer->get_pseudo_random_bytes(randomizer, len, random_bytes); - - /* overwrite mpz_t with pseudo-random bytes before clearing it */ - mpz_import(z, len, 1, 1, 1, 0, random_bytes); + memset(random, 0, len); + /* overwrite mpz_t with zero bytes before clearing it */ + mpz_import(z, len, 1, 1, 1, 0, random); mpz_clear(z); - - randomizer->destroy(randomizer); } /** @@ -176,34 +168,31 @@ static void mpz_clear_randomized(mpz_t z) static status_t compute_prime(private_gmp_rsa_private_key_t *this, size_t prime_size, mpz_t *prime) { - randomizer_t *randomizer; + rng_t *rng; chunk_t random_bytes; - status_t status; - randomizer = randomizer_create(); + rng = lib->crypto->create_rng(lib->crypto, RNG_REAL); + if (!rng) + { + DBG1("no RNG of quality %N found", rng_quality_names, RNG_REAL); + return FAILED; + } + mpz_init(*prime); - do { - status = randomizer->allocate_random_bytes(randomizer, prime_size, - &random_bytes); - if (status != SUCCESS) - { - randomizer->destroy(randomizer); - mpz_clear(*prime); - return FAILED; - } + rng->allocate_bytes(rng, prime_size, &random_bytes); /* make sure most significant bit is set */ random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80; mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); mpz_nextprime (*prime, *prime); - chunk_free_randomized(&random_bytes); + chunk_clear(&random_bytes); } /* check if it isn't too large */ while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size); - randomizer->destroy(randomizer); + rng->destroy(rng); return SUCCESS; } @@ -705,7 +694,7 @@ static gmp_rsa_private_key_t *load(chunk_t blob) { if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx)) { - chunk_free_randomized(&blob); + chunk_clear(&blob); destroy(this); return NULL; } @@ -714,7 +703,7 @@ static gmp_rsa_private_key_t *load(chunk_t blob) case PRIV_KEY_VERSION: if (object.len > 0 && *object.ptr != 0) { - chunk_free_randomized(&blob); + chunk_clear(&blob); destroy(this); return NULL; } @@ -746,7 +735,7 @@ static gmp_rsa_private_key_t *load(chunk_t blob) } objectID++; } - chunk_free_randomized(&blob); + chunk_clear(&blob); this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; if (!gmp_rsa_public_key_build_id(this->n, this->e, diff --git a/src/libstrongswan/plugins/random/Makefile.am b/src/libstrongswan/plugins/random/Makefile.am new file mode 100644 index 000000000..8b61d7094 --- /dev/null +++ b/src/libstrongswan/plugins/random/Makefile.am @@ -0,0 +1,11 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-random.la + +libstrongswan_random_la_SOURCES = random_plugin.h random_plugin.c \ + random_rng.c random_rng.h +libstrongswan_random_la_LDFLAGS = -module + diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c new file mode 100644 index 000000000..3eff81ee0 --- /dev/null +++ b/src/libstrongswan/plugins/random/random_plugin.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "random_plugin.h" + +#include +#include "random_rng.h" + +typedef struct private_random_plugin_t private_random_plugin_t; + +/** + * private data of random_plugin + */ +struct private_random_plugin_t { + + /** + * public functions + */ + random_plugin_t public; +}; + +/** + * Implementation of random_plugin_t.gmptroy + */ +static void destroy(private_random_plugin_t *this) +{ + lib->crypto->remove_rng(lib->crypto, + (rng_constructor_t)random_rng_create); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_random_plugin_t *this = malloc_thing(private_random_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + lib->crypto->add_rng(lib->crypto, RNG_STRONG, + (rng_constructor_t)random_rng_create); + lib->crypto->add_rng(lib->crypto, RNG_REAL, + (rng_constructor_t)random_rng_create); + + return &this->public.plugin; +} + diff --git a/src/libstrongswan/plugins/random/random_plugin.h b/src/libstrongswan/plugins/random/random_plugin.h new file mode 100644 index 000000000..9e8b99387 --- /dev/null +++ b/src/libstrongswan/plugins/random/random_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup random_p random + * @ingroup plugins + * + * @defgroup random_plugin random_plugin + * @{ @ingroup random_p + */ + +#ifndef RANDOM_PLUGIN_H_ +#define RANDOM_PLUGIN_H_ + +#include + +typedef struct random_plugin_t random_plugin_t; + +/** + * Plugin implementing a RNG reading from /dev/[u]random. + */ +struct random_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a random_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* RANDOM_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/random/random_rng.c b/src/libstrongswan/plugins/random/random_rng.c new file mode 100644 index 000000000..1aadc88bd --- /dev/null +++ b/src/libstrongswan/plugins/random/random_rng.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2008 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "random_rng.h" + +#ifndef DEV_RANDOM +# define DEV_RANDOM "/dev/random" +#endif + +#ifndef DEV_URANDOM +# define DEV_URANDOM "/dev/urandom" +#endif + +typedef struct private_random_rng_t private_random_rng_t; + +/** + * Private data of an random_rng_t object. + */ +struct private_random_rng_t { + + /** + * Public random_rng_t interface. + */ + random_rng_t public; + + /** + * random device, depends on quality + */ + int dev; + + /** + * file we read random bytes from + */ + char *file; +}; + +/** + * Implementation of random_rng_t.get_bytes. + */ +static void get_bytes(private_random_rng_t *this, size_t bytes, + u_int8_t *buffer) +{ + size_t done, got; + + done = 0; + + while (done < bytes) + { + got = read(this->dev, buffer + done, bytes - done); + if (got <= 0) + { + DBG1("reading from \"%s\" failed: %s, retrying...", + this->file, strerror(errno)); + close(this->dev); + sleep(1); + this->dev = open(this->file, 0); + } + done += got; + } +} + +/** + * Implementation of random_rng_t.allocate_bytes. + */ +static void allocate_bytes(private_random_rng_t *this, size_t bytes, + chunk_t *chunk) +{ + *chunk = chunk_alloc(bytes); + get_bytes(this, chunk->len, chunk->ptr); +} + +/** + * Implementation of random_rng_t.destroy. + */ +static void destroy(private_random_rng_t *this) +{ + close(this->dev); + free(this); +} + +/* + * Described in header. + */ +random_rng_t *random_rng_create(rng_quality_t quality) +{ + private_random_rng_t *this = malloc_thing(private_random_rng_t); + + /* public functions */ + this->public.rng.get_bytes = (void (*) (rng_t *, size_t, u_int8_t*)) get_bytes; + this->public.rng.allocate_bytes = (void (*) (rng_t *, size_t, chunk_t*)) allocate_bytes; + this->public.rng.destroy = (void (*) (rng_t *))destroy; + + if (quality == RNG_REAL) + { + this->file = DEV_RANDOM; + } + else + { + this->file = DEV_URANDOM; + } + + this->dev = open(this->file, 0); + if (this->dev < 0) + { + DBG1("opening \"%s\" failed: %s", this->file, strerror(errno)); + free(this); + return NULL; + } + return &this->public; +} + diff --git a/src/libstrongswan/plugins/random/random_rng.h b/src/libstrongswan/plugins/random/random_rng.h new file mode 100644 index 000000000..7f82353d8 --- /dev/null +++ b/src/libstrongswan/plugins/random/random_rng.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +/** + * @defgroup random_rng random_rng + * @{ @ingroup utils + */ + +#ifndef RANDOM_RNG_H_ +#define RANDOM_RNG_H_ + +typedef struct random_rng_t random_rng_t; + +#include + +/** + * rng_t implementation on top of /dev/[u]random + */ +struct random_rng_t { + + /** + * Implements rng_t. + */ + rng_t rng; +}; + +/** + * Creates an random_rng_t instance. + * + * @param quality required quality of randomness + * @return created random_rng_t + */ +random_rng_t *random_rng_create(rng_quality_t quality); + +#endif /*RANDOM_RNG_H_ @} */ diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index ce77359cd..9f27f2306 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -205,14 +204,18 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this) */ static chunk_t build_nonce(private_x509_ocsp_request_t *this) { - randomizer_t *randomizer; + rng_t *rng; - randomizer = randomizer_create(); - randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LEN, &this->nonce); - randomizer->destroy(randomizer); - - return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid, - asn1_simple_object(ASN1_OCTET_STRING, this->nonce)); + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (rng) + { + rng->allocate_bytes(rng, NONCE_LEN, &this->nonce); + rng->destroy(rng); + return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid, + asn1_simple_object(ASN1_OCTET_STRING, this->nonce)); + } + DBG1("creating OCSP request nonce failed, no RNG found"); + return chunk_empty; } /** diff --git a/src/libstrongswan/utils/randomizer.c b/src/libstrongswan/utils/randomizer.c deleted file mode 100644 index 74db0dead..000000000 --- a/src/libstrongswan/utils/randomizer.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * $Id$ - */ - -#include -#include -#include -#include -#include - -#include "randomizer.h" - - -typedef struct private_randomizer_t private_randomizer_t; - -/** - * Private data of an randomizer_t object. - */ -struct private_randomizer_t { - - /** - * Public randomizer_t interface. - */ - randomizer_t public; -}; - -/** - * Read bytes from the random device - */ -static status_t read_bytes(private_randomizer_t *this, - bool pseudo_random, size_t bytes, u_int8_t *buffer) -{ - size_t ndone; - int device; - size_t got; - char * device_name; - - device_name = pseudo_random ? DEV_URANDOM : DEV_RANDOM; - - device = open(device_name, 0); - if (device < 0) { - return FAILED; - } - ndone = 0; - - /* read until nbytes are read */ - while (ndone < bytes) - { - got = read(device, buffer + ndone, bytes - ndone); - if (got <= 0) { - close(device); - return FAILED; - } - ndone += got; - } - close(device); - return SUCCESS; -} - -/** - * Implementation of randomizer_t.get_random_bytes. - */ -static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, - u_int8_t *buffer) -{ - return read_bytes(this, FALSE, bytes, buffer); -} - -/** - * Implementation of randomizer_t.allocate_random_bytes. - */ -static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, - chunk_t *chunk) -{ - status_t status; - chunk->len = bytes; - chunk->ptr = malloc(bytes); - status = read_bytes(this, FALSE, bytes, chunk->ptr); - if (status != SUCCESS) - { - free(chunk->ptr); - } - return status; -} - -/** - * Implementation of randomizer_t.get_pseudo_random_bytes. - */ -static status_t get_pseudo_random_bytes(private_randomizer_t *this, - size_t bytes, u_int8_t *buffer) -{ - return read_bytes(this, TRUE, bytes, buffer); -} - -/** - * Implementation of randomizer_t.allocate_pseudo_random_bytes. - */ -static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, - size_t bytes, chunk_t *chunk) -{ - status_t status; - chunk->len = bytes; - chunk->ptr = malloc(bytes); - status = read_bytes(this, TRUE, bytes, chunk->ptr); - if (status != SUCCESS) - { - free(chunk->ptr); - } - return status; -} - -/** - * Implementation of randomizer_t.destroy. - */ -static void destroy(private_randomizer_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -randomizer_t *randomizer_create(void) -{ - private_randomizer_t *this = malloc_thing(private_randomizer_t); - - /* public functions */ - this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes; - this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes; - this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes; - this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes; - this->public.destroy = (void (*) (randomizer_t *))destroy; - - return &this->public; -} - diff --git a/src/libstrongswan/utils/randomizer.h b/src/libstrongswan/utils/randomizer.h deleted file mode 100644 index c7aa86b01..000000000 --- a/src/libstrongswan/utils/randomizer.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See . - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * $Id$ - */ - -/** - * @defgroup randomizer randomizer - * @{ @ingroup utils - */ - -#ifndef RANDOMIZER_H_ -#define RANDOMIZER_H_ - -typedef struct randomizer_t randomizer_t; - -#include - -#ifndef DEV_RANDOM -/** - * Device to read real random bytes - */ -# define DEV_RANDOM "/dev/random" -#endif - -#ifndef DEV_URANDOM -/** - * Device to read pseudo random bytes - */ -# define DEV_URANDOM "/dev/urandom" -#endif - -/** - * Class used to get random and pseudo random values. - */ -struct randomizer_t { - - /** - * Reads a specific number of bytes from random device. - * - * @param bytes number of bytes to read - * @param buffer pointer to buffer where to write the data in. - * @return SUCCESS, or FAILED - */ - status_t (*get_random_bytes) (randomizer_t *this, - size_t bytes, u_int8_t *buffer); - - /** - * Allocates space and writes in random bytes. - * - * @param bytes number of bytes to allocate - * @param chunk chunk which will hold the allocated random bytes - * @return SUCCESS, or FAILED - */ - status_t (*allocate_random_bytes) (randomizer_t *this, - size_t bytes, chunk_t *chunk); - - /** - * Reads a specific number of bytes from pseudo random device. - * - * @param bytes number of bytes to read - * @param buffer pointer to buffer where to write the data in. - * @return SUCCESS, or FAILED - */ - status_t (*get_pseudo_random_bytes) (randomizer_t *this,size_t bytes, u_int8_t *buffer); - - /** - * Allocates space and writes in pseudo random bytes. - * - * @param bytes number of bytes to allocate - * @param chunk chunk which will hold the allocated random bytes - * @return SUCCESS, or FAILED - */ - status_t (*allocate_pseudo_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk); - - /** - * Destroys a randomizer_t object. - */ - void (*destroy) (randomizer_t *this); -}; - -/** - * Creates a randomizer_t object. - * - * @return created randomizer_t - */ -randomizer_t *randomizer_create(void); - -#endif /*RANDOMIZER_H_ @} */