From 242fcd695db6225ef98c5ad084e6f15ec5953158 Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Fri, 23 Mar 2018 15:12:20 +0100 Subject: [PATCH] rand/randfile.c: permit non-regular files in RAND_load_file. Apparently applications rely on RAND_load_file's ability to work with non-regular files, customarily with /dev/urandom, so that the ban was not exactly appropriate. Reviewed-by: Rich Salz Reviewed-by: Bernd Edlinger Reviewed-by: Paul Dale Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/5737) --- crypto/rand/randfile.c | 34 +++++++++++++++++++++++++++------- doc/man3/RAND_load_file.pod | 10 +++------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index a979eb99a2..fa6f49e1b5 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 2fe932fd3f..489ff2d7f1 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. -- 2.25.1