#include "config.h" #include #include #include #include #include #include #include "logerr.h" #include "random.h" #ifdef TEST #include "testing.h" #endif int urandom_bytes(const size_t n, uint8_t (*const addr)[]) { int rc = 0; FILE *f = NULL; f = fopen("/dev/urandom", "r"); if (!f) { logerr("fopen(\"/dev/urandom\", \"r\"): %s\n", strerror(errno)); rc = -1; goto out; } const size_t read_count = fread(addr, 1, n, f); if (ferror(f)) { logerr("fread(addr, 1, n, f): %s\n", strerror(errno)); rc = -1; goto out; } assert(read_count == n); out: if (f) { if (fclose(f)) { logerr("fclose(f): %s\n", strerror(errno)); rc = -1; } } return rc; } #ifdef TEST static int test_urandom_bytes(void) { int rc = 0; test_start("urandom_bytes()"); { testing("we get to pick the size that comes out"); const size_t LEN = 256; uint8_t arr[256 /* LEN */] = { 0 }; for (size_t n = 0; n < LEN; n++) { if (urandom_bytes(n, &arr)) { logerr("urandom_bytes(n, &arr);\n"); rc = -1; goto out; } for (size_t i = n; i < LEN; i++) { assert(arr[i] == 0); } } test_ok(); } { testing("we always get a new value as a result"); const size_t LEN = 64; uint8_t arr1[64 /* LEN */] = { 0 }; uint8_t arr2[64 /* LEN */] = { 0 }; if (urandom_bytes(LEN, &arr1)) { logerr("urandom_bytes(LEN, &arr1);\n"); rc = -1; goto out; } const size_t attempts = 10; for (size_t n = 0; n < attempts; n++) { if (urandom_bytes(LEN, &arr2)) { logerr("urandom_bytes(LEN, &arr2);\n"); rc = -1; goto out; } assert(memcmp(arr1, arr2, LEN) != 0); } test_ok(); } out: return rc; } #endif #ifdef TEST int main(void) { int rc = 0; if (test_urandom_bytes()) { logerr("test_urandom_bytes();\n"); rc = -1; goto out; } out: return !!rc; } #endif