summaryrefslogtreecommitdiff
path: root/source/kit/secure_random.c
blob: 02b168b29c4a565c263ed955e61b9bef1f8f0d4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "secure_random.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(_WIN32) && !defined(__CYGWIN__)
#  ifndef WIN32_LEAN_AND_MEAN
#    define WIN32_LEAN_AND_MEAN 1
#  endif
#  include <windows.h>
#  include <wincrypt.h>
#else
#  include <unistd.h>
#endif

kit_status_t kit_secure_random(i64 size, void *data) {
  assert(size >= 0);
  assert(data != NULL);

  if (size <= 0 || data == NULL)
    return KIT_ERROR_INVALID_ARGUMENT;

#if defined(_WIN32) && !defined(__CYGWIN__)
  HCRYPTPROV prov = 0;
  if (!CryptAcquireContextW(&prov, NULL, NULL, PROV_RSA_FULL,
                            CRYPT_VERIFYCONTEXT | CRYPT_SILENT) ||
      !CryptGenRandom(prov, (DWORD) size, (BYTE *) data) ||
      !CryptReleaseContext(prov, 0))
    return KIT_ERROR_RESOURCE_UNAVAILABLE;
#else
  FILE *f = fopen("/dev/urandom", "rb");

  if (f == NULL)
    return KIT_ERROR_RESOURCE_UNAVAILABLE;

  i64 n = (i64) fread(data, 1, size, f);
  fclose(f);

  if (n != size)
    return KIT_ERROR_RESOURCE_UNAVAILABLE;
#endif

  return KIT_OK;
}