xref: /onnv-gate/usr/src/lib/libcryptoutil/common/random.c (revision 12657:87b06ab1c8e3)
15252Sdinak /*
25252Sdinak  * CDDL HEADER START
35252Sdinak  *
45252Sdinak  * The contents of this file are subject to the terms of the
55252Sdinak  * Common Development and Distribution License (the "License").
65252Sdinak  * You may not use this file except in compliance with the License.
75252Sdinak  *
85252Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95252Sdinak  * or http://www.opensolaris.org/os/licensing.
105252Sdinak  * See the License for the specific language governing permissions
115252Sdinak  * and limitations under the License.
125252Sdinak  *
135252Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
145252Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155252Sdinak  * If applicable, add the following below this CDDL HEADER, with the
165252Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
175252Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
185252Sdinak  *
195252Sdinak  * CDDL HEADER END
205252Sdinak  */
21*12657SDina.Nimeh@Sun.COM 
225252Sdinak /*
23*12657SDina.Nimeh@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
245252Sdinak  */
255252Sdinak 
265252Sdinak #include <stdio.h>
276104Sdinak #include <unistd.h>
286104Sdinak #include <errno.h>
295252Sdinak #include <string.h>
305252Sdinak #include <fcntl.h>
315252Sdinak #include <locale.h>
328932SDina.Nimeh@Sun.COM #include <stdarg.h>
335252Sdinak #include <cryptoutil.h>
349127SDina.Nimeh@Sun.COM #include <pthread.h>
355252Sdinak 
366104Sdinak 
376104Sdinak static pthread_mutex_t	random_mutex = PTHREAD_MUTEX_INITIALIZER;
386104Sdinak static pthread_mutex_t	urandom_mutex = PTHREAD_MUTEX_INITIALIZER;
396104Sdinak 
409127SDina.Nimeh@Sun.COM static pthread_mutex_t	random_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
419127SDina.Nimeh@Sun.COM static pthread_mutex_t	urandom_seed_mutex = PTHREAD_MUTEX_INITIALIZER;
426104Sdinak 
436104Sdinak #define	RANDOM_DEVICE		"/dev/random"	/* random device name */
446104Sdinak #define	URANDOM_DEVICE		"/dev/urandom"	/* urandom device name */
456104Sdinak 
466104Sdinak static int	random_fd = -1;
476104Sdinak static int	urandom_fd = -1;
486104Sdinak 
499127SDina.Nimeh@Sun.COM static int	random_seed_fd = -1;
509127SDina.Nimeh@Sun.COM static int	urandom_seed_fd = -1;
519127SDina.Nimeh@Sun.COM 
529127SDina.Nimeh@Sun.COM 
536104Sdinak /*
546104Sdinak  * Equivalent of open(2) insulated from EINTR.
556104Sdinak  * Also sets close-on-exec.
566104Sdinak  */
578932SDina.Nimeh@Sun.COM int
open_nointr(const char * path,int oflag,...)588932SDina.Nimeh@Sun.COM open_nointr(const char *path, int oflag, ...)
596104Sdinak {
606104Sdinak 	int	fd;
618932SDina.Nimeh@Sun.COM 	mode_t	pmode;
628932SDina.Nimeh@Sun.COM 	va_list	alist;
638932SDina.Nimeh@Sun.COM 
648932SDina.Nimeh@Sun.COM 	va_start(alist, oflag);
658932SDina.Nimeh@Sun.COM 	pmode = va_arg(alist, mode_t);
668932SDina.Nimeh@Sun.COM 	va_end(alist);
676104Sdinak 
686104Sdinak 	do {
698932SDina.Nimeh@Sun.COM 		if ((fd = open(path, oflag, pmode)) >= 0) {
706104Sdinak 			(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
716104Sdinak 			break;
726104Sdinak 		}
736104Sdinak 		/* errno definitely set by failed open() */
746104Sdinak 	} while (errno == EINTR);
756104Sdinak 	return (fd);
766104Sdinak }
776104Sdinak 
786104Sdinak /*
796104Sdinak  * Equivalent of read(2) insulated from EINTR.
806104Sdinak  */
818932SDina.Nimeh@Sun.COM ssize_t
readn_nointr(int fd,void * dbuf,size_t dlen)828932SDina.Nimeh@Sun.COM readn_nointr(int fd, void *dbuf, size_t dlen)
836104Sdinak {
846104Sdinak 	char	*marker = dbuf;
856104Sdinak 	size_t	left = dlen;
866104Sdinak 	ssize_t	nread = 0, err;
876104Sdinak 
886104Sdinak 	for (err = 0; left > 0 && nread != -1; marker += nread, left -= nread) {
896104Sdinak 		if ((nread = read(fd, marker, left)) < 0) {
906104Sdinak 			if (errno == EINTR) {	/* keep trying */
916104Sdinak 				nread = 0;
926104Sdinak 				continue;
936104Sdinak 			}
946104Sdinak 			err = nread;		/* hard error */
956104Sdinak 			break;
968932SDina.Nimeh@Sun.COM 		} else if (nread == 0) {
978932SDina.Nimeh@Sun.COM 			break;
988932SDina.Nimeh@Sun.COM 		}
998932SDina.Nimeh@Sun.COM 	}
1008932SDina.Nimeh@Sun.COM 	return (err != 0 ? err : dlen - left);
1018932SDina.Nimeh@Sun.COM }
1028932SDina.Nimeh@Sun.COM 
1038932SDina.Nimeh@Sun.COM /*
1048932SDina.Nimeh@Sun.COM  * Equivalent of write(2) insulated from EINTR.
1058932SDina.Nimeh@Sun.COM  */
1068932SDina.Nimeh@Sun.COM ssize_t
writen_nointr(int fd,void * dbuf,size_t dlen)1078932SDina.Nimeh@Sun.COM writen_nointr(int fd, void *dbuf, size_t dlen)
1088932SDina.Nimeh@Sun.COM {
1098932SDina.Nimeh@Sun.COM 	char	*marker = dbuf;
1108932SDina.Nimeh@Sun.COM 	size_t	left = dlen;
1118932SDina.Nimeh@Sun.COM 	ssize_t	nwrite = 0, err;
1128932SDina.Nimeh@Sun.COM 
1138932SDina.Nimeh@Sun.COM 	for (err = 0; left > 0 && nwrite != -1; marker += nwrite,
1148932SDina.Nimeh@Sun.COM 	    left -= nwrite) {
1158932SDina.Nimeh@Sun.COM 		if ((nwrite = write(fd, marker, left)) < 0) {
1168932SDina.Nimeh@Sun.COM 			if (errno == EINTR) {	/* keep trying */
1178932SDina.Nimeh@Sun.COM 				nwrite = 0;
1188932SDina.Nimeh@Sun.COM 				continue;
1198932SDina.Nimeh@Sun.COM 			}
1208932SDina.Nimeh@Sun.COM 			err = nwrite;		/* hard error */
1218932SDina.Nimeh@Sun.COM 			break;
1228932SDina.Nimeh@Sun.COM 		} else if (nwrite == 0) {
1238932SDina.Nimeh@Sun.COM 			break;
1246104Sdinak 		}
1256104Sdinak 	}
1266104Sdinak 	return (err != 0 ? err : dlen - left);
1276104Sdinak }
1286104Sdinak 
1296104Sdinak /*
1306104Sdinak  * Opens the random number generator devices if not already open.
1316104Sdinak  * Always returns the opened fd of the device, or error.
1326104Sdinak  */
1339127SDina.Nimeh@Sun.COM static int
pkcs11_open_common(int * fd,pthread_mutex_t * mtx,const char * dev,int oflag)1349127SDina.Nimeh@Sun.COM pkcs11_open_common(int *fd, pthread_mutex_t *mtx, const char *dev, int oflag)
1359127SDina.Nimeh@Sun.COM {
136*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_lock(mtx);
137*12657SDina.Nimeh@Sun.COM 	if (*fd < 0)
138*12657SDina.Nimeh@Sun.COM 		*fd = open_nointr(dev, oflag);
139*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_unlock(mtx);
140*12657SDina.Nimeh@Sun.COM 
1419127SDina.Nimeh@Sun.COM 	return (*fd);
1429127SDina.Nimeh@Sun.COM }
1439127SDina.Nimeh@Sun.COM 
1449127SDina.Nimeh@Sun.COM static int
pkcs11_open_random(void)1456104Sdinak pkcs11_open_random(void)
1466104Sdinak {
1479127SDina.Nimeh@Sun.COM 	return (pkcs11_open_common(&random_fd, &random_mutex,
1489127SDina.Nimeh@Sun.COM 	    RANDOM_DEVICE, O_RDONLY));
1499127SDina.Nimeh@Sun.COM }
1509127SDina.Nimeh@Sun.COM 
1519127SDina.Nimeh@Sun.COM static int
pkcs11_open_urandom(void)1529127SDina.Nimeh@Sun.COM pkcs11_open_urandom(void)
1539127SDina.Nimeh@Sun.COM {
1549127SDina.Nimeh@Sun.COM 	return (pkcs11_open_common(&urandom_fd, &urandom_mutex,
1559127SDina.Nimeh@Sun.COM 	    URANDOM_DEVICE, O_RDONLY));
1566104Sdinak }
1576104Sdinak 
1589127SDina.Nimeh@Sun.COM static int
pkcs11_open_random_seed(void)1599127SDina.Nimeh@Sun.COM pkcs11_open_random_seed(void)
1606104Sdinak {
1619127SDina.Nimeh@Sun.COM 	return (pkcs11_open_common(&random_seed_fd, &random_seed_mutex,
1629127SDina.Nimeh@Sun.COM 	    RANDOM_DEVICE, O_WRONLY));
1639127SDina.Nimeh@Sun.COM }
1649127SDina.Nimeh@Sun.COM 
1659127SDina.Nimeh@Sun.COM static int
pkcs11_open_urandom_seed(void)1669127SDina.Nimeh@Sun.COM pkcs11_open_urandom_seed(void)
1679127SDina.Nimeh@Sun.COM {
1689127SDina.Nimeh@Sun.COM 	return (pkcs11_open_common(&urandom_seed_fd, &urandom_seed_mutex,
1699127SDina.Nimeh@Sun.COM 	    URANDOM_DEVICE, O_WRONLY));
1706104Sdinak }
1716104Sdinak 
1726104Sdinak /*
1736104Sdinak  * Close the random number generator devices if already open.
1746104Sdinak  */
1759127SDina.Nimeh@Sun.COM static void
pkcs11_close_common(int * fd,pthread_mutex_t * mtx)1769127SDina.Nimeh@Sun.COM pkcs11_close_common(int *fd, pthread_mutex_t *mtx)
1779127SDina.Nimeh@Sun.COM {
1789127SDina.Nimeh@Sun.COM 	(void) pthread_mutex_lock(mtx);
1799127SDina.Nimeh@Sun.COM 	(void) close(*fd);
1809127SDina.Nimeh@Sun.COM 	*fd = -1;
1819127SDina.Nimeh@Sun.COM 	(void) pthread_mutex_unlock(mtx);
1829127SDina.Nimeh@Sun.COM }
1839127SDina.Nimeh@Sun.COM 
1846104Sdinak void
pkcs11_close_random(void)1856104Sdinak pkcs11_close_random(void)
1866104Sdinak {
1879127SDina.Nimeh@Sun.COM 	pkcs11_close_common(&random_fd, &random_mutex);
1886104Sdinak }
1896104Sdinak 
1906104Sdinak void
pkcs11_close_urandom(void)1916104Sdinak pkcs11_close_urandom(void)
1926104Sdinak {
1939127SDina.Nimeh@Sun.COM 	pkcs11_close_common(&urandom_fd, &urandom_mutex);
1949127SDina.Nimeh@Sun.COM }
1959127SDina.Nimeh@Sun.COM 
1969127SDina.Nimeh@Sun.COM static void
pkcs11_close_random_seed(void)1979127SDina.Nimeh@Sun.COM pkcs11_close_random_seed(void)
1989127SDina.Nimeh@Sun.COM {
1999127SDina.Nimeh@Sun.COM 	pkcs11_close_common(&random_seed_fd, &random_seed_mutex);
2009127SDina.Nimeh@Sun.COM }
2019127SDina.Nimeh@Sun.COM 
2029127SDina.Nimeh@Sun.COM void
pkcs11_close_urandom_seed(void)2039127SDina.Nimeh@Sun.COM pkcs11_close_urandom_seed(void)
2049127SDina.Nimeh@Sun.COM {
2059127SDina.Nimeh@Sun.COM 	pkcs11_close_common(&urandom_seed_fd, &urandom_seed_mutex);
2069127SDina.Nimeh@Sun.COM }
2079127SDina.Nimeh@Sun.COM 
2089127SDina.Nimeh@Sun.COM /*
209*12657SDina.Nimeh@Sun.COM  * Read from the random number generator devices.
210*12657SDina.Nimeh@Sun.COM  */
211*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_read_common(int * fd,pthread_mutex_t * mtx,void * dbuf,size_t dlen)212*12657SDina.Nimeh@Sun.COM pkcs11_read_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
213*12657SDina.Nimeh@Sun.COM {
214*12657SDina.Nimeh@Sun.COM 	size_t	n;
215*12657SDina.Nimeh@Sun.COM 
216*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_lock(mtx);
217*12657SDina.Nimeh@Sun.COM 	n = readn_nointr(*fd, dbuf, dlen);
218*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_unlock(mtx);
219*12657SDina.Nimeh@Sun.COM 
220*12657SDina.Nimeh@Sun.COM 	return (n);
221*12657SDina.Nimeh@Sun.COM }
222*12657SDina.Nimeh@Sun.COM 
223*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_read_random(void * dbuf,size_t dlen)224*12657SDina.Nimeh@Sun.COM pkcs11_read_random(void *dbuf, size_t dlen)
225*12657SDina.Nimeh@Sun.COM {
226*12657SDina.Nimeh@Sun.COM 	return (pkcs11_read_common(&random_fd, &random_mutex, dbuf, dlen));
227*12657SDina.Nimeh@Sun.COM }
228*12657SDina.Nimeh@Sun.COM 
229*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_read_urandom(void * dbuf,size_t dlen)230*12657SDina.Nimeh@Sun.COM pkcs11_read_urandom(void *dbuf, size_t dlen)
231*12657SDina.Nimeh@Sun.COM {
232*12657SDina.Nimeh@Sun.COM 	return (pkcs11_read_common(&urandom_fd, &urandom_mutex, dbuf, dlen));
233*12657SDina.Nimeh@Sun.COM }
234*12657SDina.Nimeh@Sun.COM 
235*12657SDina.Nimeh@Sun.COM /*
236*12657SDina.Nimeh@Sun.COM  * Write to the random number generator devices.
237*12657SDina.Nimeh@Sun.COM  */
238*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_write_common(int * fd,pthread_mutex_t * mtx,void * dbuf,size_t dlen)239*12657SDina.Nimeh@Sun.COM pkcs11_write_common(int *fd, pthread_mutex_t *mtx, void *dbuf, size_t dlen)
240*12657SDina.Nimeh@Sun.COM {
241*12657SDina.Nimeh@Sun.COM 	size_t	n;
242*12657SDina.Nimeh@Sun.COM 
243*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_lock(mtx);
244*12657SDina.Nimeh@Sun.COM 	n = writen_nointr(*fd, dbuf, dlen);
245*12657SDina.Nimeh@Sun.COM 	(void) pthread_mutex_unlock(mtx);
246*12657SDina.Nimeh@Sun.COM 
247*12657SDina.Nimeh@Sun.COM 	return (n);
248*12657SDina.Nimeh@Sun.COM }
249*12657SDina.Nimeh@Sun.COM 
250*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_write_random_seed(void * dbuf,size_t dlen)251*12657SDina.Nimeh@Sun.COM pkcs11_write_random_seed(void *dbuf, size_t dlen)
252*12657SDina.Nimeh@Sun.COM {
253*12657SDina.Nimeh@Sun.COM 	return (pkcs11_write_common(&random_seed_fd, &random_seed_mutex,
254*12657SDina.Nimeh@Sun.COM 	    dbuf, dlen));
255*12657SDina.Nimeh@Sun.COM }
256*12657SDina.Nimeh@Sun.COM 
257*12657SDina.Nimeh@Sun.COM static size_t
pkcs11_write_urandom_seed(void * dbuf,size_t dlen)258*12657SDina.Nimeh@Sun.COM pkcs11_write_urandom_seed(void *dbuf, size_t dlen)
259*12657SDina.Nimeh@Sun.COM {
260*12657SDina.Nimeh@Sun.COM 	return (pkcs11_write_common(&urandom_seed_fd, &urandom_seed_mutex,
261*12657SDina.Nimeh@Sun.COM 	    dbuf, dlen));
262*12657SDina.Nimeh@Sun.COM }
263*12657SDina.Nimeh@Sun.COM 
264*12657SDina.Nimeh@Sun.COM /*
2659127SDina.Nimeh@Sun.COM  * Seed /dev/random with the data in the buffer.
2669127SDina.Nimeh@Sun.COM  */
2679127SDina.Nimeh@Sun.COM int
pkcs11_seed_random(void * sbuf,size_t slen)2689127SDina.Nimeh@Sun.COM pkcs11_seed_random(void *sbuf, size_t slen)
2699127SDina.Nimeh@Sun.COM {
270*12657SDina.Nimeh@Sun.COM 	int	rv;
271*12657SDina.Nimeh@Sun.COM 
2729127SDina.Nimeh@Sun.COM 	if (sbuf == NULL || slen == 0)
2739127SDina.Nimeh@Sun.COM 		return (0);
2749127SDina.Nimeh@Sun.COM 
2759127SDina.Nimeh@Sun.COM 	/* Seeding error could mean it's not supported (errno = EACCES) */
2769127SDina.Nimeh@Sun.COM 	if (pkcs11_open_random_seed() < 0)
2779127SDina.Nimeh@Sun.COM 		return (-1);
2789127SDina.Nimeh@Sun.COM 
279*12657SDina.Nimeh@Sun.COM 	rv = -1;
280*12657SDina.Nimeh@Sun.COM 	if (pkcs11_write_random_seed(sbuf, slen) == slen)
281*12657SDina.Nimeh@Sun.COM 		rv = 0;
282*12657SDina.Nimeh@Sun.COM 
283*12657SDina.Nimeh@Sun.COM 	pkcs11_close_random_seed();
284*12657SDina.Nimeh@Sun.COM 	return (rv);
2859127SDina.Nimeh@Sun.COM }
2869127SDina.Nimeh@Sun.COM 
2879127SDina.Nimeh@Sun.COM /*
2889127SDina.Nimeh@Sun.COM  * Seed /dev/urandom with the data in the buffer.
2899127SDina.Nimeh@Sun.COM  */
2909127SDina.Nimeh@Sun.COM int
pkcs11_seed_urandom(void * sbuf,size_t slen)2919127SDina.Nimeh@Sun.COM pkcs11_seed_urandom(void *sbuf, size_t slen)
2929127SDina.Nimeh@Sun.COM {
293*12657SDina.Nimeh@Sun.COM 	int	rv;
294*12657SDina.Nimeh@Sun.COM 
2959127SDina.Nimeh@Sun.COM 	if (sbuf == NULL || slen == 0)
2969127SDina.Nimeh@Sun.COM 		return (0);
2979127SDina.Nimeh@Sun.COM 
2989127SDina.Nimeh@Sun.COM 	/* Seeding error could mean it's not supported (errno = EACCES) */
2999127SDina.Nimeh@Sun.COM 	if (pkcs11_open_urandom_seed() < 0)
3009127SDina.Nimeh@Sun.COM 		return (-1);
3019127SDina.Nimeh@Sun.COM 
302*12657SDina.Nimeh@Sun.COM 	rv = -1;
303*12657SDina.Nimeh@Sun.COM 	if (pkcs11_write_urandom_seed(sbuf, slen) == slen)
304*12657SDina.Nimeh@Sun.COM 		rv = 0;
305*12657SDina.Nimeh@Sun.COM 
306*12657SDina.Nimeh@Sun.COM 	pkcs11_close_urandom_seed();
307*12657SDina.Nimeh@Sun.COM 	return (rv);
3089127SDina.Nimeh@Sun.COM }
3099127SDina.Nimeh@Sun.COM 
3109127SDina.Nimeh@Sun.COM /*
3119127SDina.Nimeh@Sun.COM  * Put the requested amount of random data into a preallocated buffer.
3129127SDina.Nimeh@Sun.COM  * Good for token key data, persistent objects.
3139127SDina.Nimeh@Sun.COM  */
3149127SDina.Nimeh@Sun.COM int
pkcs11_get_random(void * dbuf,size_t dlen)3159127SDina.Nimeh@Sun.COM pkcs11_get_random(void *dbuf, size_t dlen)
3169127SDina.Nimeh@Sun.COM {
3179127SDina.Nimeh@Sun.COM 	if (dbuf == NULL || dlen == 0)
3189127SDina.Nimeh@Sun.COM 		return (0);
3199127SDina.Nimeh@Sun.COM 
3209127SDina.Nimeh@Sun.COM 	/* Read random data directly from /dev/random */
3219127SDina.Nimeh@Sun.COM 	if (pkcs11_open_random() < 0)
3229127SDina.Nimeh@Sun.COM 		return (-1);
3239127SDina.Nimeh@Sun.COM 
324*12657SDina.Nimeh@Sun.COM 	if (pkcs11_read_random(dbuf, dlen) == dlen)
3259127SDina.Nimeh@Sun.COM 		return (0);
3269127SDina.Nimeh@Sun.COM 	return (-1);
3276104Sdinak }
3285252Sdinak 
3295252Sdinak /*
3305252Sdinak  * Put the requested amount of random data into a preallocated buffer.
3315252Sdinak  * Good for passphrase salts, initialization vectors.
3325252Sdinak  */
3335252Sdinak int
pkcs11_get_urandom(void * dbuf,size_t dlen)3349127SDina.Nimeh@Sun.COM pkcs11_get_urandom(void *dbuf, size_t dlen)
3355252Sdinak {
3365252Sdinak 	if (dbuf == NULL || dlen == 0)
3375252Sdinak 		return (0);
3385252Sdinak 
3395252Sdinak 	/* Read random data directly from /dev/urandom */
3406104Sdinak 	if (pkcs11_open_urandom() < 0)
3416104Sdinak 		return (-1);
3426104Sdinak 
343*12657SDina.Nimeh@Sun.COM 	if (pkcs11_read_urandom(dbuf, dlen) == dlen)
3446104Sdinak 		return (0);
3455252Sdinak 	return (-1);
3465252Sdinak }
3476104Sdinak 
3486104Sdinak /*
3499127SDina.Nimeh@Sun.COM  * Same as pkcs11_get_urandom but ensures non zero data.
3506104Sdinak  */
3516104Sdinak int
pkcs11_get_nzero_urandom(void * dbuf,size_t dlen)3529127SDina.Nimeh@Sun.COM pkcs11_get_nzero_urandom(void *dbuf, size_t dlen)
3536104Sdinak {
3546104Sdinak 	char	extrarand[32];
3556104Sdinak 	size_t	bytesleft = 0;
3566104Sdinak 	size_t	i = 0;
3576104Sdinak 
3586104Sdinak 	/* Start with some random data */
3599127SDina.Nimeh@Sun.COM 	if (pkcs11_get_urandom(dbuf, dlen) < 0)
3606104Sdinak 		return (-1);
3616104Sdinak 
3626104Sdinak 	/* Walk through data replacing any 0 bytes with more random data */
3636104Sdinak 	while (i < dlen) {
3646104Sdinak 		if (((char *)dbuf)[i] != 0) {
3656104Sdinak 			i++;
3666104Sdinak 			continue;
3676104Sdinak 		}
3686104Sdinak 
3696104Sdinak 		if (bytesleft == 0) {
3706104Sdinak 			bytesleft = sizeof (extrarand);
3719127SDina.Nimeh@Sun.COM 			if (pkcs11_get_urandom(extrarand, bytesleft) < 0)
3726104Sdinak 				return (-1);
3736104Sdinak 		}
3746104Sdinak 		bytesleft--;
3756104Sdinak 
3766104Sdinak 		((char *)dbuf)[i] = extrarand[bytesleft];
3776104Sdinak 	}
3786104Sdinak 	return (0);
3796104Sdinak }
380