diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-26 12:03:54 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-07-26 15:19:25 +0200 |
commit | 6953f021907ee9bc95380d576debbc653436b96a (patch) | |
tree | 7d855d0d624fa26b0a9657a9315aae5e3276be9e | |
parent | e9d97be44f1b210e34982da5e2370aa12d2b18ba (diff) | |
download | gnutls-6953f021907ee9bc95380d576debbc653436b96a.tar.gz |
getrandom: loop around getrandom to get the requested number of bytes
This simplifies and enhanced the previous error handling code.
-rw-r--r-- | lib/nettle/rnd-linux.c | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/lib/nettle/rnd-linux.c b/lib/nettle/rnd-linux.c index 3f59332977..3ad9056cb3 100644 --- a/lib/nettle/rnd-linux.c +++ b/lib/nettle/rnd-linux.c @@ -71,13 +71,33 @@ static unsigned have_getrandom(void) return 0; } -static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size) +/* returns exactly the amount of bytes requested */ +static int force_getrandom(void *buf, size_t buflen, unsigned int flags) { + int left = buflen; int ret; - do { - ret = getrandom(_rnd, size, 0); - } while (ret == -1 && errno == EINTR); + uint8_t *p = buf; + + while (left > 0) { + ret = getrandom(p, left, flags); + if (ret == -1) { + if (errno != EINTR) + return ret; + } + + if (ret > 0) { + left -= ret; + p += ret; + } + } + + return buflen; +} +static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size) +{ + int ret; + ret = force_getrandom(_rnd, size, 0); if (ret == -1) { int e = errno; gnutls_assert(); @@ -87,25 +107,6 @@ static int _rnd_get_system_entropy_getrandom(void* _rnd, size_t size) return GNUTLS_E_RANDOM_DEVICE_ERROR; } - /* Since this function is only used internally for small sizes, - * any limits of getrandom() are not reached. The only way - * to receive less data than asked, is due to a signal interrupting - * the system call. In that case we retry. */ - if ((size_t)ret != size) { - unsigned i; - for (i=0;i<3;i++) { - do { - ret = getrandom(_rnd, size, 0); - } while (ret == -1 && errno == EINTR); - - if ((size_t)ret == size) - break; - } - - if (ret == -1 || (size_t)ret != size) - return gnutls_assert_val(GNUTLS_E_RANDOM_DEVICE_ERROR); - } - return 0; } #else |