Merge branch 'upstream'
[nativeclient.git] / service_runtime / nacl_global_secure_random.c
blobd0e76bfcb3d948293990049134dcd9a6d2c19f3f
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Service Runtime. Secure RNG abstraction.
36 #include "native_client/service_runtime/nacl_global_secure_random.h"
38 #include "native_client/service_runtime/nacl_log.h"
39 #include "native_client/service_runtime/nacl_secure_random.h"
40 #include "native_client/service_runtime/nacl_sync.h"
41 #include "native_client/service_runtime/nacl_sync_checked.h"
44 * Initialization occurs in nacl_globals.c
46 struct NaClMutex nacl_global_rng_mu;
47 struct NaClSecureRng nacl_global_rng;
49 void NaClGlobalSecureRngInit(void)
51 NaClMutexCtor(&nacl_global_rng_mu);
52 if (!NaClSecureRngCtor(&nacl_global_rng)) {
53 NaClLog(LOG_FATAL,
54 "Could not construct global random number generator.\n");
58 void NaClGlobalSecureRngFini(void)
60 NaClSecureRngDtor(&nacl_global_rng);
61 NaClMutexDtor(&nacl_global_rng_mu);
64 int32_t NaClGlobalSecureRngUniform(int32_t range_max)
66 int32_t rv;
68 NaClXMutexLock(&nacl_global_rng_mu);
69 rv = NaClSecureRngUniform(&nacl_global_rng, range_max);
70 NaClXMutexUnlock(&nacl_global_rng_mu);
71 return rv;
74 void NaClGenerateRandomPath(char *path, int length)
77 * This function is used for generating random paths and names, e.g. for
78 * IMC sockets and semaphores.
80 * IMC sockets note: the IMC header file omits some important
81 * details. The alphabet cannot include backslash for Windows. For
82 * Linux, it uses the abstract namespace (see unix(7)), and can
83 * contain arbitrary characters. The limitations for OSX are the
84 * same as for pathname components, since the IMC library uses
85 * unix-domain sockets there.
87 * We uniformly generate from an alphabet of digits and uppercase and
88 * lowercase alphabetic characters on case-sensitive platforms
89 * (non-Windows), and uniformly generate from an alphabet of digits
90 * and lowercase characters on case-insensitive platforms (Windows).
91 * Since IMC allows 28 characters, we can compute the (apparent)
92 * entropy which gives the effort required by an attacker who cannot
93 * enumerate the namespace but must probe blindly. ("Apparent",
94 * since the actual amount of entropy available is the entropy in the
95 * cryptographically secure pseudorandom number generator's seed.)
97 * For case sensitive names (linux, osx), we have an alphabet size of
98 * 62 characters, so assuming that the underlying generator is ideal,
99 * we have a total entropy of the name is
101 * H_{28} = 28 * H_1 = 28 * (-\log_2(1/62))
102 * \approx 166.72 bits
104 * For case insensitive names (windows), we have an alphabet size of
105 * 36 characters, and we have
107 * H_{28} = 28 * H_1 = 28 * -log_2(1/36)
108 * \approx 144.76 bits
110 * If we used the 62-character alphabet in a case insensitive
111 * environment then the case folding means that an attacker will
112 * encounter an entropy of
114 * H_{28} = 28 * H_1 = 28 * (10/62 * -log_2(1/62) + 26*2/62 * -log_2(2/62))
115 * \approx 143.23 bits
117 * which reduces security by 1.52 bits. So, using an equiprobable
118 * alphabet rather than case folding is slightly better in a case
119 * insensitive environment, and using a larger alphabet is much
120 * better than always case folding in a case sensitive environment
121 * (23.48 bits).
123 * TODO: determine if the alphabets can be enlarged, and by how
124 * much.
126 static char const alphabet[] = ("abcdefghijklmnopqrstuvwxyz"
127 #if !NACL_WINDOWS
128 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
129 #endif /* !NACL_WINDOWS */
130 "0123456789");
131 int const alphabet_size = sizeof alphabet - 1; /* NUL termination */
133 int i;
134 int r;
136 for (i = 0; i < length-1; ++i) {
137 r = NaClGlobalSecureRngUniform(alphabet_size);
138 path[i] = alphabet[r];
140 path[length-1] = '\0';