diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index a979eb99a259a4993c91233ee1438afd9dc9b460..fa6f49e1b5d57787ff30b23920ca0bd035f9b3e8 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -32,6 +32,8 @@ # define chmod _chmod # define open _open # define fdopen _fdopen +# define fstat _fstat +# define fileno _fileno # endif #endif @@ -82,27 +84,45 @@ int RAND_load_file(const char *file, long bytes) if (bytes == 0) return 0; -#ifndef OPENSSL_NO_POSIX_IO - if (stat(file, &sb) < 0 || !S_ISREG(sb.st_mode)) { - RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_NOT_A_REGULAR_FILE); + if ((in = openssl_fopen(file, "rb")) == NULL) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_CANNOT_OPEN_FILE); ERR_add_error_data(2, "Filename=", file); return -1; } -#endif - if ((in = openssl_fopen(file, "rb")) == NULL) { - RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_CANNOT_OPEN_FILE); + +#ifndef OPENSSL_NO_POSIX_IO + if (fstat(fileno(in), &sb) < 0) { + RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_INTERNAL_ERROR); ERR_add_error_data(2, "Filename=", file); return -1; } + if (!S_ISREG(sb.st_mode) && bytes < 0) + bytes = 256; +#endif + /* + * Don't buffer, because even if |file| is regular file, we have + * no control over the buffer, so why would we want a copy of its + * contents lying around? + */ + setbuf(in, NULL); + for ( ; ; ) { if (bytes > 0) n = (bytes < RAND_FILE_SIZE) ? (int)bytes : RAND_FILE_SIZE; else n = RAND_FILE_SIZE; i = fread(buf, 1, n, in); - if (i <= 0) +#ifdef EINTR + if (ferror(in) && errno == EINTR){ + clearerr(in); + if (i == 0) + continue; + } +#endif + if (i == 0) break; + RAND_add(buf, i, (double)i); ret += i; diff --git a/doc/man3/RAND_load_file.pod b/doc/man3/RAND_load_file.pod index 2fe932fd3f42839b11a9c92cf27b6ab8c34529ea..489ff2d7f112387f6e017edce849b7fb496ebea1 100644 --- a/doc/man3/RAND_load_file.pod +++ b/doc/man3/RAND_load_file.pod @@ -24,6 +24,9 @@ Do not load the same file multiple times unless its contents have been updated by RAND_write_file() between reads. Also, note that B should be adequately protected so that an attacker cannot replace or examine the contents. +If B is not a regular file, then user is considered to be +responsible for any side effects, e.g. non-anticipated blocking or +capture of controlling terminal. RAND_write_file() writes a number of random bytes (currently 128) to file B which can be used to initialize the PRNG by calling @@ -70,13 +73,6 @@ error. L, L -=head1 HISTORY - -A comment in the source since at least OpenSSL 1.0.2 said that -RAND_load_file() and RAND_write_file() were only intended for regular files, -and not really device special files such as C. This was -poorly enforced before OpenSSL 1.1.1. - =head1 COPYRIGHT Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.