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 : * A NaClDesc subclass that exposes the platform secure RNG
9 : * implementation.
10 : */
11 :
12 : #include <string.h>
13 :
14 : #include "native_client/src/trusted/desc/nacl_desc_rng.h"
15 :
16 : #include "native_client/src/shared/platform/nacl_secure_random.h"
17 : #include "native_client/src/shared/platform/nacl_secure_random_base.h"
18 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
19 :
20 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
21 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
22 :
23 : static struct NaClDescVtbl const kNaClDescRngVtbl; /* fwd */
24 :
25 297 : static int NaClDescRngSubclassCtor(struct NaClDescRng *self) {
26 297 : if (!NaClSecureRngCtor(&self->rng)) {
27 0 : goto rng_ctor_fail;
28 : }
29 297 : NACL_VTBL(NaClRefCount, self) =
30 : (struct NaClRefCountVtbl *) &kNaClDescRngVtbl;
31 297 : return 1;
32 :
33 : /* failure cleanup */
34 : rng_ctor_fail:
35 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
36 0 : return 0;
37 297 : }
38 :
39 294 : int NaClDescRngCtor(struct NaClDescRng *self) {
40 294 : int rv;
41 294 : if (!NaClDescCtor((struct NaClDesc *) self)) {
42 0 : return 0;
43 : }
44 294 : rv = NaClDescRngSubclassCtor(self);
45 294 : if (!rv) {
46 0 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
47 0 : }
48 294 : return rv;
49 294 : }
50 :
51 1 : static void NaClDescRngDtor(struct NaClRefCount *vself) {
52 1 : struct NaClDescRng *self = (struct NaClDescRng *) vself;
53 :
54 1 : (*NACL_VTBL(NaClSecureRngIf, &self->rng)->Dtor)(
55 : (struct NaClSecureRngIf *) &self->rng);
56 1 : NACL_VTBL(NaClDesc, self) = &kNaClDescVtbl;
57 1 : (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
58 1 : }
59 :
60 6 : static ssize_t NaClDescRngRead(struct NaClDesc *vself,
61 6 : void *buf,
62 6 : size_t len) {
63 6 : struct NaClDescRng *self = (struct NaClDescRng *) vself;
64 :
65 6 : (*NACL_VTBL(NaClSecureRngIf, &self->rng)->GenBytes)(
66 : (struct NaClSecureRngIf *) &self->rng, buf, len);
67 6 : return len;
68 : }
69 :
70 0 : static ssize_t NaClDescRngWrite(struct NaClDesc *vself,
71 0 : void const *buf,
72 0 : size_t len) {
73 0 : UNREFERENCED_PARAMETER(vself);
74 0 : UNREFERENCED_PARAMETER(buf);
75 :
76 : /*
77 : * Eventually we may want to have secure pseudorandom number
78 : * generators that permit mixing user-supplied data -- presumably
79 : * low entropy, from timing of events or something like that -- into
80 : * the generator state. This must be done carefully, of course,
81 : * since we would not want the user-supplied data to destroy the
82 : * internal generator's entropy.
83 : */
84 0 : return len;
85 : }
86 :
87 0 : static int NaClDescRngFstat(struct NaClDesc *vself,
88 0 : struct nacl_abi_stat *statbuf) {
89 0 : UNREFERENCED_PARAMETER(vself);
90 :
91 0 : memset(statbuf, 0, sizeof *statbuf);
92 0 : statbuf->nacl_abi_st_dev = 0;
93 : #if defined(NACL_MASK_INODES)
94 : statbuf->nacl_abi_st_ino = NACL_FAKE_INODE_NUM;
95 : #else
96 0 : statbuf->nacl_abi_st_ino = 0;
97 : #endif
98 0 : statbuf->nacl_abi_st_mode = NACL_ABI_S_IRUSR | NACL_ABI_S_IFCHR;
99 0 : statbuf->nacl_abi_st_nlink = 1;
100 0 : statbuf->nacl_abi_st_uid = -1;
101 0 : statbuf->nacl_abi_st_gid = -1;
102 0 : statbuf->nacl_abi_st_rdev = 0;
103 0 : statbuf->nacl_abi_st_size = 0;
104 0 : statbuf->nacl_abi_st_blksize = 0;
105 0 : statbuf->nacl_abi_st_blocks = 0;
106 0 : statbuf->nacl_abi_st_atime = 0;
107 0 : statbuf->nacl_abi_st_atimensec = 0;
108 0 : statbuf->nacl_abi_st_mtime = 0;
109 0 : statbuf->nacl_abi_st_mtimensec = 0;
110 0 : statbuf->nacl_abi_st_ctime = 0;
111 0 : statbuf->nacl_abi_st_ctimensec = 0;
112 :
113 0 : return 0;
114 : }
115 :
116 : /*
117 : * We allow descriptor "transfer", where in reality we create a
118 : * separate rng locally at the recipient end. This is arguably
119 : * semantically different since there is no shared access to the same
120 : * generator; on the other hand, it should be polynomial-time
121 : * indistinguishable since the output is supposed to be
122 : * cryptographically secure.
123 : */
124 3 : static int NaClDescRngExternalizeSize(struct NaClDesc *vself,
125 3 : size_t *nbytes,
126 3 : size_t *nhandles) {
127 3 : return NaClDescExternalizeSize(vself, nbytes, nhandles);
128 : }
129 :
130 3 : static int NaClDescRngExternalize(struct NaClDesc *vself,
131 3 : struct NaClDescXferState *xfer) {
132 3 : return NaClDescExternalize(vself, xfer);
133 : }
134 :
135 : static struct NaClDescVtbl const kNaClDescRngVtbl = {
136 : {
137 : NaClDescRngDtor,
138 : },
139 : NaClDescMapNotImplemented,
140 : NACL_DESC_UNMAP_NOT_IMPLEMENTED
141 : NaClDescRngRead,
142 : NaClDescRngWrite,
143 : NaClDescSeekNotImplemented,
144 : NaClDescPReadNotImplemented,
145 : NaClDescPWriteNotImplemented,
146 : NaClDescRngFstat,
147 : NaClDescGetdentsNotImplemented,
148 : NaClDescRngExternalizeSize,
149 : NaClDescRngExternalize,
150 : NaClDescLockNotImplemented,
151 : NaClDescTryLockNotImplemented,
152 : NaClDescUnlockNotImplemented,
153 : NaClDescWaitNotImplemented,
154 : NaClDescTimedWaitAbsNotImplemented,
155 : NaClDescSignalNotImplemented,
156 : NaClDescBroadcastNotImplemented,
157 : NaClDescSendMsgNotImplemented,
158 : NaClDescRecvMsgNotImplemented,
159 : NaClDescLowLevelSendMsgNotImplemented,
160 : NaClDescLowLevelRecvMsgNotImplemented,
161 : NaClDescConnectAddrNotImplemented,
162 : NaClDescAcceptConnNotImplemented,
163 : NaClDescPostNotImplemented,
164 : NaClDescSemWaitNotImplemented,
165 : NaClDescGetValueNotImplemented,
166 : NaClDescSetMetadata,
167 : NaClDescGetMetadata,
168 : NaClDescSetFlags,
169 : NaClDescGetFlags,
170 : NaClDescIsattyNotImplemented,
171 : NACL_DESC_DEVICE_RNG,
172 : };
173 :
174 3 : int NaClDescRngInternalize(struct NaClDesc **out_desc,
175 3 : struct NaClDescXferState *xfer,
176 3 : struct NaClDescQuotaInterface *quota_interface) {
177 3 : int rv;
178 3 : struct NaClDescRng *rng = malloc(sizeof *rng);
179 :
180 6 : UNREFERENCED_PARAMETER(xfer);
181 6 : UNREFERENCED_PARAMETER(quota_interface);
182 3 : if (NULL == rng) {
183 0 : rv = -NACL_ABI_ENOMEM;
184 0 : goto cleanup;
185 : }
186 3 : if (!NaClDescInternalizeCtor((struct NaClDesc *) rng, xfer)) {
187 0 : free(rng);
188 0 : rng = NULL;
189 0 : rv = -NACL_ABI_ENOMEM;
190 0 : goto cleanup;
191 : }
192 3 : if (!NaClDescRngSubclassCtor(rng)) {
193 0 : rv = -NACL_ABI_EIO;
194 0 : goto cleanup;
195 : }
196 3 : *out_desc = (struct NaClDesc *) rng;
197 3 : rv = 0; /* yay! */
198 : cleanup:
199 3 : if (rv < 0) {
200 0 : NaClDescSafeUnref((struct NaClDesc *) rng);
201 0 : }
202 3 : return rv;
203 : }
|