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