1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : /*
8 : * NaCl Service Runtime. Secure RNG implementation.
9 : */
10 :
11 : #include <errno.h>
12 : #include <string.h>
13 :
14 : #include <unistd.h>
15 : #include <sys/types.h>
16 : #include <sys/stat.h>
17 : #include <fcntl.h>
18 :
19 : #include "native_client/src/shared/platform/nacl_check.h"
20 : #include "native_client/src/shared/platform/nacl_log.h"
21 : #include "native_client/src/shared/platform/nacl_secure_random.h"
22 :
23 : #ifndef NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE
24 : # define NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE "/dev/urandom"
25 : #endif
26 :
27 : static struct NaClSecureRngIfVtbl const kNaClSecureRngVtbl;
28 :
29 : /* use -1 to ensure a fast failure if module initializer is not called */
30 : static int urandom_d = -1;
31 :
32 : /*
33 : * This sets a /dev/urandom file descriptor for this module to use.
34 : * This is for use inside outer sandboxes where opening /dev/urandom
35 : * with open() does not work.
36 : *
37 : * This function should be called before NaClSecureRngModuleInit() so
38 : * that we do not attempt to use open() inside the outer sandbox.
39 : *
40 : * This takes ownership of the file descriptor.
41 : */
42 0 : void NaClSecureRngModuleSetUrandomFd(int fd) {
43 0 : CHECK(urandom_d == -1);
44 0 : urandom_d = fd;
45 0 : }
46 :
47 : void NaClSecureRngModuleInit(void) {
48 : /*
49 : * Check whether we have already been initialised via
50 : * NaClSecureRngModuleSetUrandomFd().
51 : */
52 331 : if (urandom_d != -1) {
53 1 : return;
54 : }
55 :
56 330 : urandom_d = open(NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE, O_RDONLY, 0);
57 330 : if (-1 == urandom_d) {
58 0 : NaClLog(LOG_FATAL, "Cannot open system random source %s\n",
59 : NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE);
60 0 : }
61 331 : }
62 :
63 : void NaClSecureRngModuleFini(void) {
64 53 : if (urandom_d != -1) {
65 53 : if (close(urandom_d) != 0) {
66 0 : NaClLog(LOG_FATAL,
67 : "NaClSecureRngModuleFini: close() failed with errno %d\n",
68 0 : errno);
69 0 : }
70 53 : urandom_d = -1;
71 53 : }
72 53 : }
73 :
74 628 : int NaClSecureRngCtor(struct NaClSecureRng *self) {
75 628 : self->base.vtbl = &kNaClSecureRngVtbl;
76 628 : self->nvalid = 0;
77 628 : return 1;
78 : }
79 :
80 0 : int NaClSecureRngTestingCtor(struct NaClSecureRng *self,
81 0 : uint8_t *seed_material,
82 0 : size_t seed_bytes) {
83 0 : UNREFERENCED_PARAMETER(self);
84 0 : UNREFERENCED_PARAMETER(seed_material);
85 0 : UNREFERENCED_PARAMETER(seed_bytes);
86 0 : return 0;
87 : }
88 :
89 54 : static void NaClSecureRngDtor(struct NaClSecureRngIf *vself) {
90 54 : struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
91 162 : memset(self->buf, 0, sizeof self->buf);
92 54 : vself->vtbl = NULL;
93 54 : return;
94 : }
95 :
96 307 : static void NaClSecureRngFilbuf(struct NaClSecureRng *self) {
97 921 : VCHECK(-1 != urandom_d,
98 : ("NaClSecureRngCtor: random descriptor invalid;"
99 : " module initialization failed?\n"));
100 307 : self->nvalid = read(urandom_d, self->buf, sizeof self->buf);
101 307 : if (self->nvalid <= 0) {
102 0 : NaClLog(LOG_FATAL, "NaClSecureRngFilbuf failed, read returned %d\n",
103 : self->nvalid);
104 0 : }
105 307 : }
106 :
107 31314 : static uint8_t NaClSecureRngGenByte(struct NaClSecureRngIf *vself) {
108 31314 : struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
109 :
110 31314 : if (0 > self->nvalid) {
111 0 : NaClLog(LOG_FATAL,
112 : "NaClSecureRngGenByte: illegal buffer state, nvalid = %d\n",
113 : self->nvalid);
114 0 : }
115 31314 : if (0 == self->nvalid) {
116 307 : NaClSecureRngFilbuf(self);
117 307 : }
118 : /* 0 < self->nvalid <= sizeof self->buf */
119 31314 : return self->buf[--self->nvalid];
120 : }
121 :
122 : static struct NaClSecureRngIfVtbl const kNaClSecureRngVtbl = {
123 : NaClSecureRngDtor,
124 : NaClSecureRngGenByte,
125 : NaClSecureRngDefaultGenUint32,
126 : NaClSecureRngDefaultGenBytes,
127 : NaClSecureRngDefaultUniform,
128 : };
|