xref: /titanic_52/usr/src/lib/libcryptoutil/common/random.c (revision 05d57413471eaaa425913a06edc2ab33ad9b05bc)
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
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
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
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
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
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
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
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
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
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
18726ff1ce9Sdinak pkcs11_close_random(void)
18826ff1ce9Sdinak {
1897b79d846SDina K Nimeh 	pkcs11_close_common(&random_fd, &random_mutex);
19026ff1ce9Sdinak }
19126ff1ce9Sdinak 
192*05d57413SDan McDonald static 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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