4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <locale.h>
32 #include <stdarg.h>
33 #include <cryptoutil.h>
34 #include <pthread.h>
35
36
37 static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
38 static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
39
40 static pthread_mutex_t random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
41 static pthread_mutex_t urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
42
43 #define RANDOM_DEVICE "/dev/random" /* random device name */
44 #define URANDOM_DEVICE "/dev/urandom" /* urandom device name */
45
46 static int random_fd = -1;
47 static int urandom_fd = -1;
48
49 static int random_seed_fd = -1;
50 static int urandom_seed_fd = -1;
51
52
53 /*
54 * Equivalent of open(2) insulated from EINTR.
55 * Also sets close-on-exec.
164
165 static int
166 pkcs11_open_urandom_seed(void)
167 {
168 return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
169 URANDOM_DEVICE, O_WRONLY));
170 }
171
172 /*
173 * Close the random number generator devices if already open.
174 */
175 static void
176 pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
177 {
178 (void) pthread_mutex_lock(mtx);
179 (void) close(*fd);
180 *fd = -1;
181 (void) pthread_mutex_unlock(mtx);
182 }
183
184 void
185 pkcs11_close_random(void)
186 {
187 pkcs11_close_common(&random_fd, &random_mutex);
188 }
189
190 void
191 pkcs11_close_urandom(void)
192 {
193 pkcs11_close_common(&urandom_fd, &urandom_mutex);
194 }
195
196 static void
197 pkcs11_close_random_seed(void)
198 {
199 pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
200 }
201
202 void
203 pkcs11_close_urandom_seed(void)
204 {
205 pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
206 }
207
208 /*
209 * Read from the random number generator devices.
210 */
211 static size_t
212 pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
213 {
214 size_t n;
215
216 (void) pthread_mutex_lock(mtx);
217 n = readn_nointr(*fd, dbuf, dlen);
218 (void) pthread_mutex_unlock(mtx);
219
220 return (n);
221 }
222
359 if (pkcs11_get_urandom(dbuf, dlen) < 0)
360 return (-1);
361
362 /* Walk through data replacing any 0 bytes with more random data */
363 while (i < dlen) {
364 if (((char *)dbuf)[i] != 0) {
365 i++;
366 continue;
367 }
368
369 if (bytesleft == 0) {
370 bytesleft = sizeof (extrarand);
371 if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
372 return (-1);
373 }
374 bytesleft--;
375
376 ((char *)dbuf)[i] = extrarand[bytesleft];
377 }
378 return (0);
379 }
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
25 */
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <locale.h>
33 #include <stdarg.h>
34 #include <cryptoutil.h>
35 #include <pthread.h>
36
37 #pragma init(pkcs11_random_init)
38
39 static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
40 static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
41
42 static pthread_mutex_t random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
43 static pthread_mutex_t urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
44
45 #define RANDOM_DEVICE "/dev/random" /* random device name */
46 #define URANDOM_DEVICE "/dev/urandom" /* urandom device name */
47
48 static int random_fd = -1;
49 static int urandom_fd = -1;
50
51 static int random_seed_fd = -1;
52 static int urandom_seed_fd = -1;
53
54
55 /*
56 * Equivalent of open(2) insulated from EINTR.
57 * Also sets close-on-exec.
166
167 static int
168 pkcs11_open_urandom_seed(void)
169 {
170 return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
171 URANDOM_DEVICE, O_WRONLY));
172 }
173
174 /*
175 * Close the random number generator devices if already open.
176 */
177 static void
178 pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
179 {
180 (void) pthread_mutex_lock(mtx);
181 (void) close(*fd);
182 *fd = -1;
183 (void) pthread_mutex_unlock(mtx);
184 }
185
186 static void
187 pkcs11_close_random(void)
188 {
189 pkcs11_close_common(&random_fd, &random_mutex);
190 }
191
192 static void
193 pkcs11_close_urandom(void)
194 {
195 pkcs11_close_common(&urandom_fd, &urandom_mutex);
196 }
197
198 static void
199 pkcs11_close_random_seed(void)
200 {
201 pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
202 }
203
204 static void
205 pkcs11_close_urandom_seed(void)
206 {
207 pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
208 }
209
210 /*
211 * Read from the random number generator devices.
212 */
213 static size_t
214 pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
215 {
216 size_t n;
217
218 (void) pthread_mutex_lock(mtx);
219 n = readn_nointr(*fd, dbuf, dlen);
220 (void) pthread_mutex_unlock(mtx);
221
222 return (n);
223 }
224
361 if (pkcs11_get_urandom(dbuf, dlen) < 0)
362 return (-1);
363
364 /* Walk through data replacing any 0 bytes with more random data */
365 while (i < dlen) {
366 if (((char *)dbuf)[i] != 0) {
367 i++;
368 continue;
369 }
370
371 if (bytesleft == 0) {
372 bytesleft = sizeof (extrarand);
373 if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
374 return (-1);
375 }
376 bytesleft--;
377
378 ((char *)dbuf)[i] = extrarand[bytesleft];
379 }
380 return (0);
381 }
382
383 static void
384 pkcs11_random_prepare(void)
385 {
386 /*
387 * NOTE - None of these are acquired more than one at a time.
388 * I can therefore acquire all four without fear of deadlock.
389 */
390 (void) pthread_mutex_lock(&random_mutex);
391 (void) pthread_mutex_lock(&urandom_mutex);
392 (void) pthread_mutex_lock(&random_seed_mutex);
393 (void) pthread_mutex_lock(&urandom_seed_mutex);
394 }
395
396 static void
397 pkcs11_random_parent_post(void)
398 {
399 /* Drop the mutexes and get back to work! */
400 (void) pthread_mutex_unlock(&urandom_seed_mutex);
401 (void) pthread_mutex_unlock(&random_seed_mutex);
402 (void) pthread_mutex_unlock(&urandom_mutex);
403 (void) pthread_mutex_unlock(&random_mutex);
404 }
405
406 static void
407 pkcs11_random_child_post(void)
408 {
409 pkcs11_random_parent_post();
410
411 /* Also, close the FDs, just in case. */
412 pkcs11_close_random();
413 pkcs11_close_urandom();
414 pkcs11_close_random_seed();
415 pkcs11_close_urandom_seed();
416 }
417
418 static void
419 pkcs11_random_init(void)
420 {
421 (void) pthread_atfork(pkcs11_random_prepare, pkcs11_random_parent_post,
422 pkcs11_random_child_post);
423 }
|