Commit 98cb9592 authored by Vladimír Čunát's avatar Vladimír Čunát

buffer randomness from gnutls

gnutls_rnd() is more heavy-weight than I originally anticipated,
and in simple profiling it would take roughly 1% of CPU.
With this simple buffering the usage dropped well under 0.1%.
parent f8867141
......@@ -989,6 +989,40 @@ int knot_dname_lf2wire(knot_dname_t * const dst, uint8_t len, const uint8_t *lf)
return d - dst;
}
static void rnd_noerror(void *data, uint size)
{
int ret = gnutls_rnd(GNUTLS_RND_NONCE, data, size);
if (ret) {
kr_log_error("gnutls_rnd(): %s\n", gnutls_strerror(ret));
abort();
}
}
void kr_rnd_buffered(void *data, uint size)
{
/* static circular buffer, from index _begin (inclusive) to _end (exclusive) */
static uint8_t buf[512/8]; /* gnutls_rnd() works on blocks of 512 bits (chacha) */
static uint buf_begin = sizeof(buf);
if (unlikely(size > sizeof(buf))) {
rnd_noerror(data, size);
return;
}
/* Start with contiguous chunk, possibly until the end of buffer. */
const uint size1 = MIN(size, sizeof(buf) - buf_begin);
uint8_t *d = data;
memcpy(d, buf + buf_begin, size1);
if (size1 == size) {
buf_begin += size1;
return;
}
d += size1;
size -= size1;
/* Refill the whole buffer, and finish by another contiguous chunk. */
rnd_noerror(buf, sizeof(buf));
memcpy(d, buf, size);
buf_begin = size;
}
void kr_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner,
uint16_t type, uint16_t rclass, uint32_t ttl)
{
......
......@@ -183,23 +183,21 @@ typedef array_t(ranked_rr_array_entry_t *) ranked_rr_array_t;
KR_EXPORT
char* kr_strcatdup(unsigned n, ...);
/** You probably want kr_rand_* convenience functions instead.
* This is a buffered version of gnutls_rnd(GNUTLS_RND_NONCE, ..) */
KR_EXPORT
void kr_rnd_buffered(void *data, unsigned int size);
/** Return a few random bytes. */
static inline uint64_t kr_rand_bytes(int size)
{
/* LATER(optim.): we use this to get one or two bytes typically,
* so it will probably be suitable to wrap the gnutls function
* by a buffer (size to be determined by profiling, perhaps). */
uint64_t result;
if (size <= 0 || size > sizeof(result)) {
kr_log_error("kr_rand_bytes(): EINVAL\n");
abort();
}
uint8_t data[sizeof(result)];
int ret = gnutls_rnd(GNUTLS_RND_NONCE, data, size);
if (ret) {
kr_log_error("gnutls_rnd(): %s\n", gnutls_strerror(ret));
abort();
}
kr_rnd_buffered(data, size);
/* I would have liked to dump the random data into a size_t directly,
* but that would work well only on little-endian machines,
* so intsead I hope that the compiler will optimize this out.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment