device_random.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/common/device_random.h>
  6. #include <aws/common/byte_buf.h>
  7. #include <aws/common/thread.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. static int s_rand_fd = -1;
  11. static aws_thread_once s_rand_init = AWS_THREAD_ONCE_STATIC_INIT;
  12. #ifdef O_CLOEXEC
  13. # define OPEN_FLAGS (O_RDONLY | O_CLOEXEC)
  14. #else
  15. # define OPEN_FLAGS (O_RDONLY)
  16. #endif
  17. static void s_init_rand(void *user_data) {
  18. (void)user_data;
  19. s_rand_fd = open("/dev/urandom", OPEN_FLAGS);
  20. if (s_rand_fd == -1) {
  21. s_rand_fd = open("/dev/urandom", O_RDONLY);
  22. if (s_rand_fd == -1) {
  23. abort();
  24. }
  25. }
  26. if (-1 == fcntl(s_rand_fd, F_SETFD, FD_CLOEXEC)) {
  27. abort();
  28. }
  29. }
  30. static int s_fallback_device_random_buffer(struct aws_byte_buf *output) {
  31. aws_thread_call_once(&s_rand_init, s_init_rand, NULL);
  32. size_t diff = output->capacity - output->len;
  33. ssize_t amount_read = read(s_rand_fd, output->buffer + output->len, diff);
  34. if (amount_read != diff) {
  35. return aws_raise_error(AWS_ERROR_RANDOM_GEN_FAILED);
  36. }
  37. output->len += diff;
  38. return AWS_OP_SUCCESS;
  39. }
  40. int aws_device_random_buffer(struct aws_byte_buf *output) {
  41. return s_fallback_device_random_buffer(output);
  42. }