summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin Buckley <calvin@cmpct.info>2019-10-13 12:55:58 -0300
committerAndreas Kling <awesomekling@gmail.com>2019-10-13 18:03:21 +0200
commit5050f7b5eec273344ab91335d4ebdbbcbc487689 (patch)
tree4bd7b401be191d3bcc3fd2bd50a908fdef55c48b
parentaa42f56210bad3253008de1cbbc7e6cf33e46c7e (diff)
downloadserenity-5050f7b5eec273344ab91335d4ebdbbcbc487689.zip
Kernel: Use word-sized entropy as much as possible in syscall
-rw-r--r--Kernel/Process.cpp25
-rw-r--r--Libraries/LibC/stdlib.cpp3
2 files changed, 19 insertions, 9 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index ed70fc25b7..84f02cef54 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -3088,12 +3088,25 @@ int Process::sys$getrandom(void* buffer, size_t buffer_size, unsigned int flags
if (!validate_write(buffer, buffer_size))
return -EFAULT;
- // XXX: We probably lose a lot of entropy here, out of an already marginal
- // PRNG. A better implementation would not throw away bits for the sake of
- // array indexing, and use a better PRNG in the first place.
- uint8_t* bytes = (uint8_t*)buffer;
- for (size_t i = 0; i < buffer_size; i++)
- bytes[i] = (uint8_t)(RandomDevice::random_value() % 255);
+
+ // We prefer to get whole words of entropy.
+ // If the length is unaligned, we can work with bytes instead.
+ // Mask out the bottom two bits for words.
+ size_t words_len = buffer_size & ~3;
+ if (words_len) {
+ uint32_t* words = (uint32_t*)buffer;
+ for (size_t i = 0; i < words_len / 4; i++)
+ words[i] = RandomDevice::random_value();
+ }
+ // The remaining non-whole word bytes we can fill in.
+ size_t bytes_len = buffer_size & 3;
+ if (bytes_len) {
+ uint8_t* bytes = (uint8_t*)buffer + words_len;
+ // Get a whole word of entropy to use.
+ uint32_t word = RandomDevice::random_value();
+ for (size_t i = 0; i < bytes_len; i++)
+ bytes[i] = ((uint8_t*)&word)[i];
+ }
return 0;
}
diff --git a/Libraries/LibC/stdlib.cpp b/Libraries/LibC/stdlib.cpp
index 791e680f4e..94c23b23a0 100644
--- a/Libraries/LibC/stdlib.cpp
+++ b/Libraries/LibC/stdlib.cpp
@@ -511,9 +511,6 @@ unsigned long long strtoull(const char* str, char** endptr, int base)
uint32_t arc4random(void)
{
char buf[4];
- // XXX: RandomDevice does return a uint32_t but the syscall works with
- // a byte at a time. It could be better optimzied for this use case
- // while remaining generic.
syscall(SC_getrandom, buf, 4, 0);
return *(uint32_t*)buf;
}