GetEntropyRandomSeed.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #define _GNU_SOURCE
  16. #include "crypto/random/seed/GetEntropyRandomSeed.h"
  17. #include "util/Identity.h"
  18. #include "util/Bits.h"
  19. #include <unistd.h>
  20. #include <errno.h>
  21. #include <sys/syscall.h>
  22. #if defined(__OPENBSD__)
  23. // just use the builtin getentropy
  24. #define getEntropy getentropy
  25. #else
  26. // getentropy is available in glibc >= 2.25
  27. // to avoid a whole bunch of edgecases we shim this anyway
  28. // we can drop this when every major system with SYS_getrandom
  29. // has getentropy in its libc
  30. static int getEntropy(void *buf, size_t buflen)
  31. {
  32. int ret;
  33. if (buflen > 256) {
  34. goto failure;
  35. }
  36. ret = syscall(SYS_getrandom, buf, buflen, 0);
  37. if (ret < 0) {
  38. return ret;
  39. }
  40. if ((size_t)ret == buflen) {
  41. return 0;
  42. }
  43. failure:
  44. errno = EIO;
  45. return -1;
  46. }
  47. #endif
  48. static int get(RandomSeed_t* randomSeed, uint64_t output[8])
  49. {
  50. if (getEntropy(output, 64) < 0) {
  51. return -1;
  52. } else {
  53. return 0;
  54. }
  55. }
  56. RandomSeed_t* GetEntropyRandomSeed_new(struct Allocator* alloc)
  57. {
  58. return Allocator_clone(alloc, (&(RandomSeed_t) {
  59. .get = get,
  60. .name = "getentropy(2)"
  61. }));
  62. }