11c9bd843Sdinak /*
21c9bd843Sdinak * CDDL HEADER START
31c9bd843Sdinak *
41c9bd843Sdinak * The contents of this file are subject to the terms of the
51c9bd843Sdinak * Common Development and Distribution License (the "License").
61c9bd843Sdinak * You may not use this file except in compliance with the License.
71c9bd843Sdinak *
81c9bd843Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91c9bd843Sdinak * or http://www.opensolaris.org/os/licensing.
101c9bd843Sdinak * See the License for the specific language governing permissions
111c9bd843Sdinak * and limitations under the License.
121c9bd843Sdinak *
131c9bd843Sdinak * When distributing Covered Code, include this CDDL HEADER in each
141c9bd843Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151c9bd843Sdinak * If applicable, add the following below this CDDL HEADER, with the
161c9bd843Sdinak * fields enclosed by brackets "[]" replaced with your own identifying
171c9bd843Sdinak * information: Portions Copyright [yyyy] [name of copyright owner]
181c9bd843Sdinak *
191c9bd843Sdinak * CDDL HEADER END
201c9bd843Sdinak */
2141cf421dSDina K Nimeh
221c9bd843Sdinak /*
2341cf421dSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*05d57413SDan McDonald * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
251c9bd843Sdinak */
261c9bd843Sdinak
271c9bd843Sdinak #include <stdio.h>
2826ff1ce9Sdinak #include <unistd.h>
2926ff1ce9Sdinak #include <errno.h>
301c9bd843Sdinak #include <string.h>
311c9bd843Sdinak #include <fcntl.h>
321c9bd843Sdinak #include <locale.h>
3319193bb6SDina K Nimeh #include <stdarg.h>
341c9bd843Sdinak #include <cryptoutil.h>
3526ff1ce9Sdinak #include <pthread.h>
3626ff1ce9Sdinak
37*05d57413SDan McDonald #pragma init(pkcs11_random_init)
387b79d846SDina K Nimeh
3926ff1ce9Sdinak static pthread_mutex_t random_mutex = PTHREAD_MUTEX_INITIALIZER;
4026ff1ce9Sdinak static pthread_mutex_t urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
4126ff1ce9Sdinak
427b79d846SDina K Nimeh static pthread_mutex_t random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
437b79d846SDina K Nimeh static pthread_mutex_t urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
4426ff1ce9Sdinak
4526ff1ce9Sdinak #define RANDOM_DEVICE "/dev/random" /* random device name */
4626ff1ce9Sdinak #define URANDOM_DEVICE "/dev/urandom" /* urandom device name */
4726ff1ce9Sdinak
4826ff1ce9Sdinak static int random_fd = -1;
4926ff1ce9Sdinak static int urandom_fd = -1;
5026ff1ce9Sdinak
517b79d846SDina K Nimeh static int random_seed_fd = -1;
527b79d846SDina K Nimeh static int urandom_seed_fd = -1;
537b79d846SDina K Nimeh
547b79d846SDina K Nimeh
5526ff1ce9Sdinak /*
5626ff1ce9Sdinak * Equivalent of open(2) insulated from EINTR.
5726ff1ce9Sdinak * Also sets close-on-exec.
5826ff1ce9Sdinak */
5919193bb6SDina K Nimeh int
open_nointr(const char * path,int oflag,...)6019193bb6SDina K Nimeh open_nointr(const char *path, int oflag, ...)
6126ff1ce9Sdinak {
6226ff1ce9Sdinak int fd;
6319193bb6SDina K Nimeh mode_t pmode;
6419193bb6SDina K Nimeh va_list alist;
6519193bb6SDina K Nimeh
6619193bb6SDina K Nimeh va_start(alist, oflag);
6719193bb6SDina K Nimeh pmode = va_arg(alist, mode_t);
6819193bb6SDina K Nimeh va_end(alist);
6926ff1ce9Sdinak
7026ff1ce9Sdinak do {
7119193bb6SDina K Nimeh if ((fd = open(path, oflag, pmode)) >= 0) {
7226ff1ce9Sdinak (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
7326ff1ce9Sdinak break;
7426ff1ce9Sdinak }
7526ff1ce9Sdinak /* errno definitely set by failed open() */
7626ff1ce9Sdinak } while (errno == EINTR);
7726ff1ce9Sdinak return (fd);
7826ff1ce9Sdinak }
7926ff1ce9Sdinak
8026ff1ce9Sdinak /*
8126ff1ce9Sdinak * Equivalent of read(2) insulated from EINTR.
8226ff1ce9Sdinak */
8319193bb6SDina K Nimeh ssize_t
readn_nointr(int fd,void * dbuf,size_t dlen)8419193bb6SDina K Nimeh readn_nointr(int fd, void *dbuf, size_t dlen)
8526ff1ce9Sdinak {
8626ff1ce9Sdinak char *marker = dbuf;
8726ff1ce9Sdinak size_t left = dlen;
8826ff1ce9Sdinak ssize_t nread = 0, err;
8926ff1ce9Sdinak
9026ff1ce9Sdinak for (err = 0; left > 0 && nread != -1; marker += nread, left -= nread) {
9126ff1ce9Sdinak if ((nread = read(fd, marker, left)) < 0) {
9226ff1ce9Sdinak if (errno == EINTR) { /* keep trying */
9326ff1ce9Sdinak nread = 0;
9426ff1ce9Sdinak continue;
9526ff1ce9Sdinak }
9626ff1ce9Sdinak err = nread; /* hard error */
9726ff1ce9Sdinak break;
9819193bb6SDina K Nimeh } else if (nread == 0) {
9919193bb6SDina K Nimeh break;
10019193bb6SDina K Nimeh }
10119193bb6SDina K Nimeh }
10219193bb6SDina K Nimeh return (err != 0 ? err : dlen - left);
10319193bb6SDina K Nimeh }
10419193bb6SDina K Nimeh
10519193bb6SDina K Nimeh /*
10619193bb6SDina K Nimeh * Equivalent of write(2) insulated from EINTR.
10719193bb6SDina K Nimeh */
10819193bb6SDina K Nimeh ssize_t
writen_nointr(int fd,void * dbuf,size_t dlen)10919193bb6SDina K Nimeh writen_nointr(int fd, void *dbuf, size_t dlen)
11019193bb6SDina K Nimeh {
11119193bb6SDina K Nimeh char *marker = dbuf;
11219193bb6SDina K Nimeh size_t left = dlen;
11319193bb6SDina K Nimeh ssize_t nwrite = 0, err;
11419193bb6SDina K Nimeh
11519193bb6SDina K Nimeh for (err = 0; left > 0 && nwrite != -1; marker += nwrite,
11619193bb6SDina K Nimeh left -= nwrite) {
11719193bb6SDina K Nimeh if ((nwrite = write(fd, marker, left)) < 0) {
11819193bb6SDina K Nimeh if (errno == EINTR) { /* keep trying */
11919193bb6SDina K Nimeh nwrite = 0;
12019193bb6SDina K Nimeh continue;
12119193bb6SDina K Nimeh }
12219193bb6SDina K Nimeh err = nwrite; /* hard error */
12319193bb6SDina K Nimeh break;
12419193bb6SDina K Nimeh } else if (nwrite == 0) {
12519193bb6SDina K Nimeh break;
12626ff1ce9Sdinak }
12726ff1ce9Sdinak }
12826ff1ce9Sdinak return (err != 0 ? err : dlen - left);
12926ff1ce9Sdinak }
13026ff1ce9Sdinak
13126ff1ce9Sdinak /*
13226ff1ce9Sdinak * Opens the random number generator devices if not already open.
13326ff1ce9Sdinak * Always returns the opened fd of the device, or error.
13426ff1ce9Sdinak */
1357b79d846SDina K Nimeh static int
pkcs11_open_common(int * fd,pthread_mutex_t * mtx,const char * dev,int oflag)1367b79d846SDina K Nimeh pkcs11_open_common(int *fd, pthread_mutex_t *mtx, const char *dev, int oflag)
13726ff1ce9Sdinak {
1387b79d846SDina K Nimeh (void) pthread_mutex_lock(mtx);
1397b79d846SDina K Nimeh if (*fd < 0)
1407b79d846SDina K Nimeh *fd = open_nointr(dev, oflag);
1417b79d846SDina K Nimeh (void) pthread_mutex_unlock(mtx);
14241cf421dSDina K Nimeh
1437b79d846SDina K Nimeh return (*fd);
14426ff1ce9Sdinak }
14526ff1ce9Sdinak
1467b79d846SDina K Nimeh static int
pkcs11_open_random(void)1477b79d846SDina K Nimeh pkcs11_open_random(void)
1487b79d846SDina K Nimeh {
1497b79d846SDina K Nimeh return (pkcs11_open_common(&random_fd, &random_mutex,
1507b79d846SDina K Nimeh RANDOM_DEVICE, O_RDONLY));
1517b79d846SDina K Nimeh }
1527b79d846SDina K Nimeh
1537b79d846SDina K Nimeh static int
pkcs11_open_urandom(void)15426ff1ce9Sdinak pkcs11_open_urandom(void)
15526ff1ce9Sdinak {
1567b79d846SDina K Nimeh return (pkcs11_open_common(&urandom_fd, &urandom_mutex,
1577b79d846SDina K Nimeh URANDOM_DEVICE, O_RDONLY));
1587b79d846SDina K Nimeh }
1597b79d846SDina K Nimeh
1607b79d846SDina K Nimeh static int
pkcs11_open_random_seed(void)1617b79d846SDina K Nimeh pkcs11_open_random_seed(void)
1627b79d846SDina K Nimeh {
1637b79d846SDina K Nimeh return (pkcs11_open_common(&random_seed_fd, &random_seed_mutex,
1647b79d846SDina K Nimeh RANDOM_DEVICE, O_WRONLY));
1657b79d846SDina K Nimeh }
1667b79d846SDina K Nimeh
1677b79d846SDina K Nimeh static int
pkcs11_open_urandom_seed(void)1687b79d846SDina K Nimeh pkcs11_open_urandom_seed(void)
1697b79d846SDina K Nimeh {
1707b79d846SDina K Nimeh return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
1717b79d846SDina K Nimeh URANDOM_DEVICE, O_WRONLY));
17226ff1ce9Sdinak }
17326ff1ce9Sdinak
17426ff1ce9Sdinak /*
17526ff1ce9Sdinak * Close the random number generator devices if already open.
17626ff1ce9Sdinak */
1777b79d846SDina K Nimeh static void
pkcs11_close_common(int * fd,pthread_mutex_t * mtx)1787b79d846SDina K Nimeh pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
1797b79d846SDina K Nimeh {
1807b79d846SDina K Nimeh (void) pthread_mutex_lock(mtx);
1817b79d846SDina K Nimeh (void) close(*fd);
1827b79d846SDina K Nimeh *fd = -1;
1837b79d846SDina K Nimeh (void) pthread_mutex_unlock(mtx);
1847b79d846SDina K Nimeh }
1857b79d846SDina K Nimeh
186*05d57413SDan McDonald static void
pkcs11_close_random(void)18726ff1ce9Sdinak pkcs11_close_random(void)
18826ff1ce9Sdinak {
1897b79d846SDina K Nimeh pkcs11_close_common(&random_fd, &random_mutex);
19026ff1ce9Sdinak }
19126ff1ce9Sdinak
192*05d57413SDan McDonald static void
pkcs11_close_urandom(void)19326ff1ce9Sdinak pkcs11_close_urandom(void)
19426ff1ce9Sdinak {
1957b79d846SDina K Nimeh pkcs11_close_common(&urandom_fd, &urandom_mutex);
1967b79d846SDina K Nimeh }
1977b79d846SDina K Nimeh
1987b79d846SDina K Nimeh static void
pkcs11_close_random_seed(void)1997b79d846SDina K Nimeh pkcs11_close_random_seed(void)
2007b79d846SDina K Nimeh {
2017b79d846SDina K Nimeh pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
2027b79d846SDina K Nimeh }
2037b79d846SDina K Nimeh
204*05d57413SDan McDonald static void
pkcs11_close_urandom_seed(void)2057b79d846SDina K Nimeh pkcs11_close_urandom_seed(void)
2067b79d846SDina K Nimeh {
2077b79d846SDina K Nimeh pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
2087b79d846SDina K Nimeh }
2097b79d846SDina K Nimeh
2107b79d846SDina K Nimeh /*
21141cf421dSDina K Nimeh * Read from the random number generator devices.
21241cf421dSDina K Nimeh */
21341cf421dSDina K Nimeh static size_t
pkcs11_read_common(int * fd,pthread_mutex_t * mtx,void * dbuf,size_t dlen)21441cf421dSDina K Nimeh pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
21541cf421dSDina K Nimeh {
21641cf421dSDina K Nimeh size_t n;
21741cf421dSDina K Nimeh
21841cf421dSDina K Nimeh (void) pthread_mutex_lock(mtx);
21941cf421dSDina K Nimeh n = readn_nointr(*fd, dbuf, dlen);
22041cf421dSDina K Nimeh (void) pthread_mutex_unlock(mtx);
22141cf421dSDina K Nimeh
22241cf421dSDina K Nimeh return (n);
22341cf421dSDina K Nimeh }
22441cf421dSDina K Nimeh
22541cf421dSDina K Nimeh static size_t
pkcs11_read_random(void * dbuf,size_t dlen)22641cf421dSDina K Nimeh pkcs11_read_random(void *dbuf, size_t dlen)
22741cf421dSDina K Nimeh {
22841cf421dSDina K Nimeh return (pkcs11_read_common(&random_fd, &random_mutex, dbuf, dlen));
22941cf421dSDina K Nimeh }
23041cf421dSDina K Nimeh
23141cf421dSDina K Nimeh static size_t
pkcs11_read_urandom(void * dbuf,size_t dlen)23241cf421dSDina K Nimeh pkcs11_read_urandom(void *dbuf, size_t dlen)
23341cf421dSDina K Nimeh {
23441cf421dSDina K Nimeh return (pkcs11_read_common(&urandom_fd, &urandom_mutex, dbuf, dlen));
23541cf421dSDina K Nimeh }
23641cf421dSDina K Nimeh
23741cf421dSDina K Nimeh /*
23841cf421dSDina K Nimeh * Write to the random number generator devices.
23941cf421dSDina K Nimeh */
24041cf421dSDina K Nimeh static size_t
pkcs11_write_common(int * fd,pthread_mutex_t * mtx,void * dbuf,size_t dlen)24141cf421dSDina K Nimeh pkcs11_write_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
24241cf421dSDina K Nimeh {
24341cf421dSDina K Nimeh size_t n;
24441cf421dSDina K Nimeh
24541cf421dSDina K Nimeh (void) pthread_mutex_lock(mtx);
24641cf421dSDina K Nimeh n = writen_nointr(*fd, dbuf, dlen);
24741cf421dSDina K Nimeh (void) pthread_mutex_unlock(mtx);
24841cf421dSDina K Nimeh
24941cf421dSDina K Nimeh return (n);
25041cf421dSDina K Nimeh }
25141cf421dSDina K Nimeh
25241cf421dSDina K Nimeh static size_t
pkcs11_write_random_seed(void * dbuf,size_t dlen)25341cf421dSDina K Nimeh pkcs11_write_random_seed(void *dbuf, size_t dlen)
25441cf421dSDina K Nimeh {
25541cf421dSDina K Nimeh return (pkcs11_write_common(&random_seed_fd, &random_seed_mutex,
25641cf421dSDina K Nimeh dbuf, dlen));
25741cf421dSDina K Nimeh }
25841cf421dSDina K Nimeh
25941cf421dSDina K Nimeh static size_t
pkcs11_write_urandom_seed(void * dbuf,size_t dlen)26041cf421dSDina K Nimeh pkcs11_write_urandom_seed(void *dbuf, size_t dlen)
26141cf421dSDina K Nimeh {
26241cf421dSDina K Nimeh return (pkcs11_write_common(&urandom_seed_fd, &urandom_seed_mutex,
26341cf421dSDina K Nimeh dbuf, dlen));
26441cf421dSDina K Nimeh }
26541cf421dSDina K Nimeh
26641cf421dSDina K Nimeh /*
2677b79d846SDina K Nimeh * Seed /dev/random with the data in the buffer.
2687b79d846SDina K Nimeh */
2697b79d846SDina K Nimeh int
pkcs11_seed_random(void * sbuf,size_t slen)2707b79d846SDina K Nimeh pkcs11_seed_random(void *sbuf, size_t slen)
2717b79d846SDina K Nimeh {
27241cf421dSDina K Nimeh int rv;
27341cf421dSDina K Nimeh
2747b79d846SDina K Nimeh if (sbuf == NULL || slen == 0)
2757b79d846SDina K Nimeh return (0);
2767b79d846SDina K Nimeh
2777b79d846SDina K Nimeh /* Seeding error could mean it's not supported (errno = EACCES) */
2787b79d846SDina K Nimeh if (pkcs11_open_random_seed() < 0)
2797b79d846SDina K Nimeh return (-1);
2807b79d846SDina K Nimeh
28141cf421dSDina K Nimeh rv = -1;
28241cf421dSDina K Nimeh if (pkcs11_write_random_seed(sbuf, slen) == slen)
28341cf421dSDina K Nimeh rv = 0;
28441cf421dSDina K Nimeh
2857b79d846SDina K Nimeh pkcs11_close_random_seed();
28641cf421dSDina K Nimeh return (rv);
2877b79d846SDina K Nimeh }
2887b79d846SDina K Nimeh
2897b79d846SDina K Nimeh /*
2907b79d846SDina K Nimeh * Seed /dev/urandom with the data in the buffer.
2917b79d846SDina K Nimeh */
2927b79d846SDina K Nimeh int
pkcs11_seed_urandom(void * sbuf,size_t slen)2937b79d846SDina K Nimeh pkcs11_seed_urandom(void *sbuf, size_t slen)
2947b79d846SDina K Nimeh {
29541cf421dSDina K Nimeh int rv;
29641cf421dSDina K Nimeh
2977b79d846SDina K Nimeh if (sbuf == NULL || slen == 0)
2987b79d846SDina K Nimeh return (0);
2997b79d846SDina K Nimeh
3007b79d846SDina K Nimeh /* Seeding error could mean it's not supported (errno = EACCES) */
3017b79d846SDina K Nimeh if (pkcs11_open_urandom_seed() < 0)
3027b79d846SDina K Nimeh return (-1);
3037b79d846SDina K Nimeh
30441cf421dSDina K Nimeh rv = -1;
30541cf421dSDina K Nimeh if (pkcs11_write_urandom_seed(sbuf, slen) == slen)
30641cf421dSDina K Nimeh rv = 0;
30741cf421dSDina K Nimeh
3087b79d846SDina K Nimeh pkcs11_close_urandom_seed();
30941cf421dSDina K Nimeh return (rv);
3107b79d846SDina K Nimeh }
3117b79d846SDina K Nimeh
3127b79d846SDina K Nimeh /*
3137b79d846SDina K Nimeh * Put the requested amount of random data into a preallocated buffer.
3147b79d846SDina K Nimeh * Good for token key data, persistent objects.
3157b79d846SDina K Nimeh */
3167b79d846SDina K Nimeh int
pkcs11_get_random(void * dbuf,size_t dlen)3177b79d846SDina K Nimeh pkcs11_get_random(void *dbuf, size_t dlen)
3187b79d846SDina K Nimeh {
3197b79d846SDina K Nimeh if (dbuf == NULL || dlen == 0)
3207b79d846SDina K Nimeh return (0);
3217b79d846SDina K Nimeh
3227b79d846SDina K Nimeh /* Read random data directly from /dev/random */
3237b79d846SDina K Nimeh if (pkcs11_open_random() < 0)
3247b79d846SDina K Nimeh return (-1);
3257b79d846SDina K Nimeh
32641cf421dSDina K Nimeh if (pkcs11_read_random(dbuf, dlen) == dlen)
3277b79d846SDina K Nimeh return (0);
3287b79d846SDina K Nimeh return (-1);
32926ff1ce9Sdinak }
3301c9bd843Sdinak
3311c9bd843Sdinak /*
3321c9bd843Sdinak * Put the requested amount of random data into a preallocated buffer.
3331c9bd843Sdinak * Good for passphrase salts, initialization vectors.
3341c9bd843Sdinak */
3351c9bd843Sdinak int
pkcs11_get_urandom(void * dbuf,size_t dlen)3367b79d846SDina K Nimeh pkcs11_get_urandom(void *dbuf, size_t dlen)
3371c9bd843Sdinak {
3381c9bd843Sdinak if (dbuf == NULL || dlen == 0)
3391c9bd843Sdinak return (0);
3401c9bd843Sdinak
3411c9bd843Sdinak /* Read random data directly from /dev/urandom */
34226ff1ce9Sdinak if (pkcs11_open_urandom() < 0)
3431c9bd843Sdinak return (-1);
34426ff1ce9Sdinak
34541cf421dSDina K Nimeh if (pkcs11_read_urandom(dbuf, dlen) == dlen)
34626ff1ce9Sdinak return (0);
34726ff1ce9Sdinak return (-1);
34826ff1ce9Sdinak }
34926ff1ce9Sdinak
35026ff1ce9Sdinak /*
3517b79d846SDina K Nimeh * Same as pkcs11_get_urandom but ensures non zero data.
35226ff1ce9Sdinak */
35326ff1ce9Sdinak int
pkcs11_get_nzero_urandom(void * dbuf,size_t dlen)3547b79d846SDina K Nimeh pkcs11_get_nzero_urandom(void *dbuf, size_t dlen)
35526ff1ce9Sdinak {
35626ff1ce9Sdinak char extrarand[32];
35726ff1ce9Sdinak size_t bytesleft = 0;
35826ff1ce9Sdinak size_t i = 0;
35926ff1ce9Sdinak
36026ff1ce9Sdinak /* Start with some random data */
3617b79d846SDina K Nimeh if (pkcs11_get_urandom(dbuf, dlen) < 0)
36226ff1ce9Sdinak return (-1);
36326ff1ce9Sdinak
36426ff1ce9Sdinak /* Walk through data replacing any 0 bytes with more random data */
36526ff1ce9Sdinak while (i < dlen) {
36626ff1ce9Sdinak if (((char *)dbuf)[i] != 0) {
36726ff1ce9Sdinak i++;
36826ff1ce9Sdinak continue;
36926ff1ce9Sdinak }
37026ff1ce9Sdinak
37126ff1ce9Sdinak if (bytesleft == 0) {
37226ff1ce9Sdinak bytesleft = sizeof (extrarand);
3737b79d846SDina K Nimeh if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
37426ff1ce9Sdinak return (-1);
37526ff1ce9Sdinak }
37626ff1ce9Sdinak bytesleft--;
37726ff1ce9Sdinak
37826ff1ce9Sdinak ((char *)dbuf)[i] = extrarand[bytesleft];
37926ff1ce9Sdinak }
38026ff1ce9Sdinak return (0);
3811c9bd843Sdinak }
382*05d57413SDan McDonald
383*05d57413SDan McDonald static void
pkcs11_random_prepare(void)384*05d57413SDan McDonald pkcs11_random_prepare(void)
385*05d57413SDan McDonald {
386*05d57413SDan McDonald /*
387*05d57413SDan McDonald * NOTE - None of these are acquired more than one at a time.
388*05d57413SDan McDonald * I can therefore acquire all four without fear of deadlock.
389*05d57413SDan McDonald */
390*05d57413SDan McDonald (void) pthread_mutex_lock(&random_mutex);
391*05d57413SDan McDonald (void) pthread_mutex_lock(&urandom_mutex);
392*05d57413SDan McDonald (void) pthread_mutex_lock(&random_seed_mutex);
393*05d57413SDan McDonald (void) pthread_mutex_lock(&urandom_seed_mutex);
394*05d57413SDan McDonald }
395*05d57413SDan McDonald
396*05d57413SDan McDonald static void
pkcs11_random_parent_post(void)397*05d57413SDan McDonald pkcs11_random_parent_post(void)
398*05d57413SDan McDonald {
399*05d57413SDan McDonald /* Drop the mutexes and get back to work! */
400*05d57413SDan McDonald (void) pthread_mutex_unlock(&urandom_seed_mutex);
401*05d57413SDan McDonald (void) pthread_mutex_unlock(&random_seed_mutex);
402*05d57413SDan McDonald (void) pthread_mutex_unlock(&urandom_mutex);
403*05d57413SDan McDonald (void) pthread_mutex_unlock(&random_mutex);
404*05d57413SDan McDonald }
405*05d57413SDan McDonald
406*05d57413SDan McDonald static void
pkcs11_random_child_post(void)407*05d57413SDan McDonald pkcs11_random_child_post(void)
408*05d57413SDan McDonald {
409*05d57413SDan McDonald pkcs11_random_parent_post();
410*05d57413SDan McDonald
411*05d57413SDan McDonald /* Also, close the FDs, just in case. */
412*05d57413SDan McDonald pkcs11_close_random();
413*05d57413SDan McDonald pkcs11_close_urandom();
414*05d57413SDan McDonald pkcs11_close_random_seed();
415*05d57413SDan McDonald pkcs11_close_urandom_seed();
416*05d57413SDan McDonald }
417*05d57413SDan McDonald
418*05d57413SDan McDonald static void
pkcs11_random_init(void)419*05d57413SDan McDonald pkcs11_random_init(void)
420*05d57413SDan McDonald {
421*05d57413SDan McDonald (void) pthread_atfork(pkcs11_random_prepare, pkcs11_random_parent_post,
422*05d57413SDan McDonald pkcs11_random_child_post);
423*05d57413SDan McDonald }
424