summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-07-26 12:03:54 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-07-26 15:19:25 +0200
commit6953f021907ee9bc95380d576debbc653436b96a (patch)
tree7d855d0d624fa26b0a9657a9315aae5e3276be9e
parente9d97be44f1b210e34982da5e2370aa12d2b18ba (diff)
downloadgnutls-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.c47
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