1 : /*
2 : * Copyright (c) 2011 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 abstraction.
9 : */
10 :
11 : #include "native_client/src/shared/platform/nacl_global_secure_random.h"
12 : #include "native_client/src/shared/platform/nacl_log.h"
13 : #include "native_client/src/shared/platform/nacl_secure_random.h"
14 : #include "native_client/src/shared/platform/nacl_sync.h"
15 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
16 :
17 : static struct NaClMutex nacl_global_rng_mu;
18 : static struct NaClSecureRng nacl_global_rng;
19 :
20 : static struct NaClSecureRng *nacl_grngp = &nacl_global_rng;
21 :
22 15 : void NaClGlobalSecureRngInit(void) {
23 15 : NaClXMutexCtor(&nacl_global_rng_mu);
24 15 : if (!NaClSecureRngCtor(nacl_grngp)) {
25 : NaClLog(LOG_FATAL,
26 0 : "Could not construct global random number generator.\n");
27 : }
28 15 : }
29 :
30 11 : void NaClGlobalSecureRngFini(void) {
31 11 : (*nacl_grngp->base.vtbl->Dtor)(&nacl_grngp->base);
32 11 : NaClMutexDtor(&nacl_global_rng_mu);
33 11 : }
34 :
35 0 : void NaClGlobalSecureRngSwitchRngForTesting(struct NaClSecureRng *rng) {
36 0 : NaClXMutexLock(&nacl_global_rng_mu);
37 0 : nacl_grngp = rng;
38 0 : NaClXMutexUnlock(&nacl_global_rng_mu);
39 0 : }
40 :
41 2 : int32_t NaClGlobalSecureRngUniform(int32_t range_max) {
42 : int32_t rv;
43 :
44 2 : NaClXMutexLock(&nacl_global_rng_mu);
45 2 : rv = (*nacl_grngp->base.vtbl->Uniform)(&nacl_grngp->base, range_max);
46 2 : NaClXMutexUnlock(&nacl_global_rng_mu);
47 2 : return rv;
48 2 : }
49 :
50 0 : uint32_t NaClGlobalSecureRngUint32(void) {
51 : uint32_t rv;
52 0 : NaClXMutexLock(&nacl_global_rng_mu);
53 0 : rv = (*nacl_grngp->base.vtbl->GenUint32)(&nacl_grngp->base);
54 0 : NaClXMutexUnlock(&nacl_global_rng_mu);
55 0 : return rv;
56 0 : }
57 :
58 0 : void NaClGlobalSecureRngGenerateBytes(uint8_t *buf, size_t buf_size) {
59 0 : NaClXMutexLock(&nacl_global_rng_mu);
60 0 : (*nacl_grngp->base.vtbl->GenBytes)(&nacl_grngp->base, buf, buf_size);
61 0 : NaClXMutexUnlock(&nacl_global_rng_mu);
62 0 : }
63 :
64 2 : void NaClGenerateRandomPath(char *path, int length) {
65 : /*
66 : * This function is used for generating random paths and names,
67 : * e.g. for IMC sockets and semaphores.
68 : *
69 : * IMC sockets note: the IMC header file omits some important
70 : * details. The alphabet cannot include backslash for Windows. For
71 : * Linux, it uses the abstract namespace (see unix(7)), and can
72 : * contain arbitrary characters. The limitations for OSX are the
73 : * same as for pathname components, since the IMC library uses
74 : * unix-domain sockets there.
75 : *
76 : * We uniformly generate from an alphabet of digits and uppercase
77 : * and lowercase alphabetic characters on case-sensitive platforms
78 : * (non-Windows), and uniformly generate from an alphabet of digits
79 : * and lowercase characters on case-insensitive platforms (Windows).
80 : * Since IMC allows 27 characters (plus a '\0' terminator), we can
81 : * compute the (apparent) entropy which gives the effort required by
82 : * an attacker who cannot enumerate the namespace but must probe
83 : * blindly. ("Apparent", since the actual amount of entropy
84 : * available is the entropy in the cryptographically secure
85 : * pseudorandom number generator's seed.)
86 : *
87 : * For case sensitive names (linux, osx), we have an alphabet size
88 : * of 62 characters, so assuming that the underlying generator is
89 : * ideal, we have a total entropy of the name is
90 : *
91 : * H_{27} = 27 * H_1 = 27 * -\log_2(1/62)
92 : * \approx 160.76 bits
93 : *
94 : * For case insensitive names (windows), we have an alphabet size of
95 : * 36 characters, and we have
96 : *
97 : * H_{27} = 27 * H_1 = 27 * -log_2(1/36)
98 : * \approx 137.59 bits
99 : *
100 : * If we used the 62-character alphabet in a case insensitive
101 : * environment then the case folding means that an attacker will
102 : * encounter an entropy of
103 : *
104 : * H_{27} = 27 * H_1 = 27 * (10/62 * -log_2(1/62) + 26*2/62 * -log_2(2/62))
105 : * \approx 138.12 bits
106 : *
107 : * which reduces security by 1.47 bits. So, using an equiprobable
108 : * alphabet rather than case folding is slightly better in a case
109 : * insensitive environment, and using a larger alphabet is much
110 : * better than always case folding in a case sensitive environment
111 : * (23.48 bits).
112 : *
113 : * TODO(bsy): determine if the alphabets can be enlarged, and by how
114 : * much.
115 : */
116 : static char const alphabet[] =
117 : "abcdefghijklmnopqrstuvwxyz"
118 : #if !NACL_WINDOWS
119 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
120 : #endif /* !NACL_WINDOWS */
121 : "0123456789";
122 2 : int const alphabet_size = sizeof alphabet - 1; /* NUL termination */
123 :
124 : int i;
125 : int r;
126 :
127 2 : for (i = 0; i < length-1; ++i) {
128 2 : r = NaClGlobalSecureRngUniform(alphabet_size);
129 2 : path[i] = alphabet[r];
130 2 : }
131 2 : path[length-1] = '\0';
132 2 : }
|