diff options
Diffstat (limited to 'usr/src/lib/libcryptoutil/common/random.c')
-rw-r--r-- | usr/src/lib/libcryptoutil/common/random.c | 55 |
1 files changed, 44 insertions, 11 deletions
diff --git a/usr/src/lib/libcryptoutil/common/random.c b/usr/src/lib/libcryptoutil/common/random.c index 6d91dbfea4..5a254ed34d 100644 --- a/usr/src/lib/libcryptoutil/common/random.c +++ b/usr/src/lib/libcryptoutil/common/random.c @@ -19,18 +19,17 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <fcntl.h> #include <locale.h> +#include <stdarg.h> #include <cryptoutil.h> #ifdef _REENTRANT @@ -60,13 +59,19 @@ static int urandom_fd = -1; * Equivalent of open(2) insulated from EINTR. * Also sets close-on-exec. */ -static int -OPEN(const char *path, int oflag) +int +open_nointr(const char *path, int oflag, ...) { int fd; + mode_t pmode; + va_list alist; + + va_start(alist, oflag); + pmode = va_arg(alist, mode_t); + va_end(alist); do { - if ((fd = open(path, oflag)) >= 0) { + if ((fd = open(path, oflag, pmode)) >= 0) { (void) fcntl(fd, F_SETFD, FD_CLOEXEC); break; } @@ -78,8 +83,8 @@ OPEN(const char *path, int oflag) /* * Equivalent of read(2) insulated from EINTR. */ -static ssize_t -READ(int fd, void *dbuf, size_t dlen) +ssize_t +readn_nointr(int fd, void *dbuf, size_t dlen) { char *marker = dbuf; size_t left = dlen; @@ -93,6 +98,34 @@ READ(int fd, void *dbuf, size_t dlen) } err = nread; /* hard error */ break; + } else if (nread == 0) { + break; + } + } + return (err != 0 ? err : dlen - left); +} + +/* + * Equivalent of write(2) insulated from EINTR. + */ +ssize_t +writen_nointr(int fd, void *dbuf, size_t dlen) +{ + char *marker = dbuf; + size_t left = dlen; + ssize_t nwrite = 0, err; + + for (err = 0; left > 0 && nwrite != -1; marker += nwrite, + left -= nwrite) { + if ((nwrite = write(fd, marker, left)) < 0) { + if (errno == EINTR) { /* keep trying */ + nwrite = 0; + continue; + } + err = nwrite; /* hard error */ + break; + } else if (nwrite == 0) { + break; } } return (err != 0 ? err : dlen - left); @@ -107,7 +140,7 @@ pkcs11_open_random(void) { RAND_LOCK(&random_mutex); if (random_fd < 0) - random_fd = OPEN(RANDOM_DEVICE, O_RDONLY); + random_fd = open_nointr(RANDOM_DEVICE, O_RDONLY); RAND_UNLOCK(&random_mutex); return (random_fd); } @@ -117,7 +150,7 @@ pkcs11_open_urandom(void) { RAND_LOCK(&urandom_mutex); if (urandom_fd < 0) - urandom_fd = OPEN(URANDOM_DEVICE, O_RDONLY); + urandom_fd = open_nointr(URANDOM_DEVICE, O_RDONLY); RAND_UNLOCK(&urandom_mutex); return (urandom_fd); } @@ -161,7 +194,7 @@ pkcs11_random_data(void *dbuf, size_t dlen) if (pkcs11_open_urandom() < 0) return (-1); - if (READ(urandom_fd, dbuf, dlen) == dlen) + if (readn_nointr(urandom_fd, dbuf, dlen) == dlen) return (0); return (-1); } |