Upstream version 10.38.222.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / desc / nacl_desc_rng.c
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 static int NaClDescRngSubclassCtor(struct NaClDescRng  *self) {
26   if (!NaClSecureRngCtor(&self->rng)) {
27     goto rng_ctor_fail;
28   }
29   NACL_VTBL(NaClRefCount, self) =
30       (struct NaClRefCountVtbl *) &kNaClDescRngVtbl;
31   return 1;
32
33   /* failure cleanup */
34  rng_ctor_fail:
35   (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
36   return 0;
37 }
38
39 int NaClDescRngCtor(struct NaClDescRng  *self) {
40   int rv;
41   if (!NaClDescCtor((struct NaClDesc *) self)) {
42     return 0;
43   }
44   rv = NaClDescRngSubclassCtor(self);
45   if (!rv) {
46     (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
47   }
48   return rv;
49 }
50
51 static void NaClDescRngDtor(struct NaClRefCount *vself) {
52   struct NaClDescRng *self = (struct NaClDescRng *) vself;
53
54   (*NACL_VTBL(NaClSecureRngIf, &self->rng)->Dtor)(
55       (struct NaClSecureRngIf *) &self->rng);
56   NACL_VTBL(NaClDesc, self) = &kNaClDescVtbl;
57   (*NACL_VTBL(NaClRefCount, self)->Dtor)((struct NaClRefCount *) self);
58 }
59
60 static ssize_t NaClDescRngRead(struct NaClDesc  *vself,
61                                void             *buf,
62                                size_t           len) {
63   struct NaClDescRng *self = (struct NaClDescRng *) vself;
64
65   (*NACL_VTBL(NaClSecureRngIf, &self->rng)->GenBytes)(
66       (struct NaClSecureRngIf *) &self->rng, buf, len);
67   return len;
68 }
69
70 static ssize_t NaClDescRngWrite(struct NaClDesc *vself,
71                                 void const      *buf,
72                                 size_t          len) {
73   UNREFERENCED_PARAMETER(vself);
74   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   return len;
85 }
86
87 static int NaClDescRngFstat(struct NaClDesc       *vself,
88                             struct nacl_abi_stat  *statbuf) {
89   UNREFERENCED_PARAMETER(vself);
90
91   memset(statbuf, 0, sizeof *statbuf);
92   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   statbuf->nacl_abi_st_ino = 0;
97 #endif
98   statbuf->nacl_abi_st_mode = NACL_ABI_S_IRUSR | NACL_ABI_S_IFCHR;
99   statbuf->nacl_abi_st_nlink = 1;
100   statbuf->nacl_abi_st_uid = -1;
101   statbuf->nacl_abi_st_gid = -1;
102   statbuf->nacl_abi_st_rdev = 0;
103   statbuf->nacl_abi_st_size = 0;
104   statbuf->nacl_abi_st_blksize = 0;
105   statbuf->nacl_abi_st_blocks = 0;
106   statbuf->nacl_abi_st_atime = 0;
107   statbuf->nacl_abi_st_atimensec = 0;
108   statbuf->nacl_abi_st_mtime = 0;
109   statbuf->nacl_abi_st_mtimensec = 0;
110   statbuf->nacl_abi_st_ctime = 0;
111   statbuf->nacl_abi_st_ctimensec = 0;
112
113   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 static int NaClDescRngExternalizeSize(struct NaClDesc *vself,
125                                       size_t          *nbytes,
126                                       size_t          *nhandles) {
127   return NaClDescExternalizeSize(vself, nbytes, nhandles);
128 }
129
130 static int NaClDescRngExternalize(struct NaClDesc           *vself,
131                                   struct NaClDescXferState  *xfer) {
132   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 int NaClDescRngInternalize(struct NaClDesc               **out_desc,
175                            struct NaClDescXferState      *xfer,
176                            struct NaClDescQuotaInterface *quota_interface) {
177   int                 rv;
178   struct NaClDescRng  *rng = malloc(sizeof *rng);
179
180   UNREFERENCED_PARAMETER(xfer);
181   UNREFERENCED_PARAMETER(quota_interface);
182   if (NULL == rng) {
183     rv = -NACL_ABI_ENOMEM;
184     goto cleanup;
185   }
186   if (!NaClDescInternalizeCtor((struct NaClDesc *) rng, xfer)) {
187     free(rng);
188     rng = NULL;
189     rv = -NACL_ABI_ENOMEM;
190     goto cleanup;
191   }
192   if (!NaClDescRngSubclassCtor(rng)) {
193     rv = -NACL_ABI_EIO;
194     goto cleanup;
195   }
196   *out_desc = (struct NaClDesc *) rng;
197   rv = 0;  /* yay! */
198  cleanup:
199   if (rv < 0) {
200     NaClDescSafeUnref((struct NaClDesc *) rng);
201   }
202   return rv;
203 }