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)
This commit is contained in:
Martin Willi 2008-04-15 05:56:35 +00:00
parent 0644ebd3de
commit 6a365f0740
33 changed files with 700 additions and 451 deletions

View File

@ -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

View 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);

View 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);

View 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,

View 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 */

View 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);

View 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);

View 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);
}
/**

View 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>

View 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;
}

View 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;
}

View 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
{

View 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);

View 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;
}

View 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);
}
}
/**

View 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

View 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);
}
/**

View 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()

View 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,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);

View 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,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.
*

View 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);

View File

@ -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",
);

View File

@ -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_ @} */

View 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);

View 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();
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,

View File

@ -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

View File

@ -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;
}

View File

@ -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_ @}*/

View File

@ -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;
}

View File

@ -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_ @} */

View 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;
}
/**

View File

@ -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;
}

View File

@ -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_ @} */