added API for random number generators, served through credential factory
authorMartin Willi <martin@strongswan.org>
Tue, 15 Apr 2008 05:56:35 +0000 (05:56 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 15 Apr 2008 05:56:35 +0000 (05:56 -0000)
ported randomizer_t to a rng_t on top of /dev/(u)random (plugin random)

33 files changed:
configure.in
src/charon/daemon.c
src/charon/encoding/payloads/encryption_payload.c
src/charon/network/receiver.c
src/charon/plugins/eap_aka/eap_aka.c
src/charon/plugins/eap_md5/eap_md5.c
src/charon/plugins/eap_sim/eap_sim.c
src/charon/plugins/stroke/stroke_cred.c
src/charon/sa/ike_sa.h
src/charon/sa/ike_sa_manager.c
src/charon/sa/tasks/child_create.c
src/charon/sa/tasks/ike_init.c
src/charon/sa/tasks/ike_me.c
src/charon/sa/tasks/ike_natd.c
src/libfast/session.c
src/libstrongswan/Makefile.am
src/libstrongswan/chunk.c
src/libstrongswan/chunk.h
src/libstrongswan/crypto/crypto_factory.c
src/libstrongswan/crypto/crypto_factory.h
src/libstrongswan/crypto/pkcs7.c
src/libstrongswan/crypto/rngs/rng.c [new file with mode: 0644]
src/libstrongswan/crypto/rngs/rng.h [new file with mode: 0644]
src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
src/libstrongswan/plugins/random/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/random/random_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/random/random_plugin.h [new file with mode: 0644]
src/libstrongswan/plugins/random/random_rng.c [new file with mode: 0644]
src/libstrongswan/plugins/random/random_rng.h [new file with mode: 0644]
src/libstrongswan/plugins/x509/x509_ocsp_request.c
src/libstrongswan/utils/randomizer.c [deleted file]
src/libstrongswan/utils/randomizer.h [deleted file]

index 9e0de9c..f9824bb 100644 (file)
@@ -224,6 +224,17 @@ AC_ARG_ENABLE(
 )
 
 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).]),
        [if test x$enableval = xyes; then
@@ -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
index e1e9a71..77a41b4 100644 (file)
@@ -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);
index cdfda3d..b74cb09 100644 (file)
@@ -27,7 +27,6 @@
 #include <encoding/generator.h>
 #include <encoding/parser.h>
 #include <utils/iterator.h>
-#include <utils/randomizer.h>
 #include <crypto/signers/signer.h>
 
 
@@ -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);
        
index 2f3bf6c..a5415c8 100644 (file)
@@ -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,
index a8bef72..570e9bf 100644 (file)
@@ -45,7 +45,6 @@
 
 #include <daemon.h>
 #include <library.h>
-#include <utils/randomizer.h>
 #include <crypto/hashers/hasher.h>
 
 /* 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 */
index 702042f..7f41b2e 100644 (file)
@@ -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);
index 70651c9..27c2c3a 100644 (file)
@@ -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);
index e27800c..4ac46ab 100644 (file)
@@ -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);
 }
 
 /**
index 1f0595c..60e499d 100644 (file)
@@ -38,7 +38,6 @@ typedef struct ike_sa_t ike_sa_t;
 #include <sa/ike_sa_id.h>
 #include <sa/child_sa.h>
 #include <sa/tasks/task.h>
-#include <utils/randomizer.h>
 #include <crypto/prfs/prf.h>
 #include <crypto/crypters/crypter.h>
 #include <crypto/signers/signer.h>
index b20cb28..a8ce872 100644 (file)
@@ -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;
 }
 
index f4f8143..9dd5add 100644 (file)
@@ -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;
 }
 
index 84df19d..8cb706a 100644 (file)
@@ -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
        {
index 58d99ea..43bafaa 100644 (file)
@@ -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);
index e8daecd..d72dd45 100644 (file)
@@ -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;
 }
 
index 519187e..87b7a26 100644 (file)
@@ -24,7 +24,6 @@
 #include <stdio.h>
 
 #include <utils/linked_list.h>
-#include <utils/randomizer.h>
 
 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);
+       }
 }
 
 /**
index e192c85..cb7e750 100644 (file)
@@ -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
index 6f12c9b..b2c9d60 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <debug.h>
 #include <printf_hook.h>
-#include <utils/randomizer.h>
 
 /**
  * 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);
 }
 
 /**
index 76acfde..b4fd2f0 100644 (file)
@@ -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()
index 1bca84f..fc904f7 100644 (file)
@@ -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,11 +96,16 @@ 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
         */
        linked_list_t *dhs;
@@ -217,6 +230,39 @@ static prf_t* create_prf(private_crypto_factory_t *this,
 }
 
 /**
+ * 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.
  */
 static diffie_hellman_t* create_dh(private_crypto_factory_t *this,
@@ -397,6 +443,43 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create)
 }
 
 /**
+ * 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.
  */
 static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group,
@@ -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);
        
index c8c2bcc..6bf070c 100644 (file)
@@ -28,6 +28,7 @@ typedef struct crypto_factory_t crypto_factory_t;
 #include <crypto/signers/signer.h>
 #include <crypto/hashers/hasher.h>
 #include <crypto/prfs/prf.h>
+#include <crypto/rngs/rng.h>
 #include <crypto/diffie_hellman.h>
 
 /**
@@ -46,11 +47,16 @@ 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
  */
 typedef diffie_hellman_t* (*dh_constructor_t)(diffie_hellman_group_t group);
@@ -96,6 +102,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.
         *
         * @param group                 diffie hellman group
@@ -176,6 +190,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.
         *
         * @param group                 dh group to constructor
index 662e8dd..13af6ac 100644 (file)
@@ -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 <stdlib.h>
@@ -30,7 +30,6 @@
 #include <crypto/hashers/hasher.h>
 #include <crypto/crypters/crypter.h>
 #include <crypto/rsa/rsa_public_key.h>
-#include <utils/randomizer.h>
 #include <utils/linked_list.h>
 
 #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 (file)
index 0000000..435e043
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 (file)
index 0000000..08f7af2
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <library.h>
+
+/**
+ * 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_ @} */
index 349ec41..7f549ef 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "gmp_diffie_hellman.h"
 
-#include <utils/randomizer.h>
 #include <debug.h>
 
 
@@ -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);
        
index c9928e6..8a4ee55 100644 (file)
@@ -26,8 +26,6 @@
 
 #include <debug.h>
 #include <asn1/asn1.h>
-#include <utils/randomizer.h>
-#include <crypto/hashers/hasher.h>
 
 /**
  *  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();
-       mpz_init(*prime);
+       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 (file)
index 0000000..8b61d70
--- /dev/null
@@ -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 (file)
index 0000000..3eff81e
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <library.h>
+#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 (file)
index 0000000..9e8b993
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <plugins/plugin.h>
+
+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 (file)
index 0000000..1aadc88
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <debug.h>
+
+#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 (file)
index 0000000..7f82353
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <library.h>
+
+/**
+ * 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_ @} */
index ce77359..9f27f23 100644 (file)
@@ -23,7 +23,6 @@
 #include <asn1/oid.h>
 #include <asn1/asn1.h>
 #include <utils/identification.h>
-#include <utils/randomizer.h>
 #include <utils/linked_list.h>
 #include <debug.h>
 #include <credentials/certificates/x509.h>
@@ -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 (file)
index 74db0de..0000000
+++ /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 <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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 <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#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 (file)
index c7aa86b..0000000
+++ /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 <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * 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 <library.h>
-
-#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_ @} */