randfile.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include "internal/cryptlib.h"
  10. #include <errno.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <openssl/crypto.h>
  15. #include <openssl/rand.h>
  16. #include <openssl/buffer.h>
  17. #ifdef OPENSSL_SYS_VMS
  18. # include <unixio.h>
  19. #endif
  20. #ifndef NO_SYS_TYPES_H
  21. # include <sys/types.h>
  22. #endif
  23. #ifndef OPENSSL_NO_POSIX_IO
  24. # include <sys/stat.h>
  25. # include <fcntl.h>
  26. /*
  27. * Following should not be needed, and we could have been stricter
  28. * and demand S_IS*. But some systems just don't comply... Formally
  29. * below macros are "anatomically incorrect", because normally they
  30. * would look like ((m) & MASK == TYPE), but since MASK availability
  31. * is as questionable, we settle for this poor-man fallback...
  32. */
  33. # if !defined(S_ISBLK)
  34. # if defined(_S_IFBLK)
  35. # define S_ISBLK(m) ((m) & _S_IFBLK)
  36. # elif defined(S_IFBLK)
  37. # define S_ISBLK(m) ((m) & S_IFBLK)
  38. # elif defined(_WIN32)
  39. # define S_ISBLK(m) 0 /* no concept of block devices on Windows */
  40. # endif
  41. # endif
  42. # if !defined(S_ISCHR)
  43. # if defined(_S_IFCHR)
  44. # define S_ISCHR(m) ((m) & _S_IFCHR)
  45. # elif defined(S_IFCHR)
  46. # define S_ISCHR(m) ((m) & S_IFCHR)
  47. # endif
  48. # endif
  49. #endif
  50. #ifdef _WIN32
  51. # define stat _stat
  52. # define chmod _chmod
  53. # define open _open
  54. # define fdopen _fdopen
  55. # define fstat _fstat
  56. # define fileno _fileno
  57. #endif
  58. #undef BUFSIZE
  59. #define BUFSIZE 1024
  60. #define RAND_DATA 1024
  61. #ifdef OPENSSL_SYS_VMS
  62. /*
  63. * Misc hacks needed for specific cases.
  64. *
  65. * __FILE_ptr32 is a type provided by DEC C headers (types.h specifically)
  66. * to make sure the FILE* is a 32-bit pointer no matter what. We know that
  67. * stdio function return this type (a study of stdio.h proves it).
  68. * Additionally, we create a similar char pointer type for the sake of
  69. * vms_setbuf below.
  70. */
  71. # if __INITIAL_POINTER_SIZE == 64
  72. # pragma pointer_size save
  73. # pragma pointer_size 32
  74. typedef char *char_ptr32;
  75. # pragma pointer_size restore
  76. /*
  77. * On VMS, setbuf() will only take 32-bit pointers, and a compilation
  78. * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
  79. * Since we know that the FILE* really is a 32-bit pointer expanded to
  80. * 64 bits, we also know it's safe to convert it back to a 32-bit pointer.
  81. * As for the buffer parameter, we only use NULL here, so that passes as
  82. * well...
  83. */
  84. # define setbuf(fp,buf) (setbuf)((__FILE_ptr32)(fp), (char_ptr32)(buf))
  85. # endif
  86. /*
  87. * This declaration is a nasty hack to get around vms' extension to fopen for
  88. * passing in sharing options being disabled by /STANDARD=ANSI89
  89. */
  90. static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
  91. (__FILE_ptr32 (*)(const char *, const char *, ...))fopen;
  92. # define VMS_OPEN_ATTRS "shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0"
  93. # define openssl_fopen(fname,mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS)
  94. #endif
  95. #define RFILE ".rnd"
  96. /*
  97. * Note that these functions are intended for seed files only. Entropy
  98. * devices and EGD sockets are handled in rand_unix.c
  99. */
  100. int RAND_load_file(const char *file, long bytes)
  101. {
  102. /*-
  103. * If bytes >= 0, read up to 'bytes' bytes.
  104. * if bytes == -1, read complete file.
  105. */
  106. unsigned char buf[BUFSIZE];
  107. #ifndef OPENSSL_NO_POSIX_IO
  108. struct stat sb;
  109. #endif
  110. int i, ret = 0, n;
  111. FILE *in = NULL;
  112. if (file == NULL)
  113. return 0;
  114. if (bytes == 0)
  115. return ret;
  116. in = openssl_fopen(file, "rb");
  117. if (in == NULL)
  118. goto err;
  119. #ifndef OPENSSL_NO_POSIX_IO
  120. /*
  121. * struct stat can have padding and unused fields that may not be
  122. * initialized in the call to stat(). We need to clear the entire
  123. * structure before calling RAND_add() to avoid complaints from
  124. * applications such as Valgrind.
  125. */
  126. memset(&sb, 0, sizeof(sb));
  127. if (fstat(fileno(in), &sb) < 0)
  128. goto err;
  129. RAND_add(&sb, sizeof(sb), 0.0);
  130. # if defined(S_ISBLK) && defined(S_ISCHR)
  131. if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
  132. /*
  133. * this file is a device. we don't want read an infinite number of
  134. * bytes from a random device, nor do we want to use buffered I/O
  135. * because we will waste system entropy.
  136. */
  137. bytes = (bytes == -1) ? 2048 : bytes; /* ok, is 2048 enough? */
  138. setbuf(in, NULL); /* don't do buffered reads */
  139. }
  140. # endif
  141. #endif
  142. for (;;) {
  143. if (bytes > 0)
  144. n = (bytes < BUFSIZE) ? (int)bytes : BUFSIZE;
  145. else
  146. n = BUFSIZE;
  147. i = fread(buf, 1, n, in);
  148. if (i <= 0)
  149. break;
  150. RAND_add(buf, i, (double)i);
  151. ret += i;
  152. if (bytes > 0) {
  153. bytes -= n;
  154. if (bytes <= 0)
  155. break;
  156. }
  157. }
  158. OPENSSL_cleanse(buf, BUFSIZE);
  159. err:
  160. if (in != NULL)
  161. fclose(in);
  162. return ret;
  163. }
  164. int RAND_write_file(const char *file)
  165. {
  166. unsigned char buf[BUFSIZE];
  167. int i, ret = 0, rand_err = 0;
  168. FILE *out = NULL;
  169. int n;
  170. #ifndef OPENSSL_NO_POSIX_IO
  171. struct stat sb;
  172. # if defined(S_ISBLK) && defined(S_ISCHR)
  173. # ifdef _WIN32
  174. /*
  175. * Check for |file| being a driver as "ASCII-safe" on Windows,
  176. * because driver paths are always ASCII.
  177. */
  178. # endif
  179. i = stat(file, &sb);
  180. if (i != -1) {
  181. if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
  182. /*
  183. * this file is a device. we don't write back to it. we
  184. * "succeed" on the assumption this is some sort of random
  185. * device. Otherwise attempting to write to and chmod the device
  186. * causes problems.
  187. */
  188. return 1;
  189. }
  190. }
  191. # endif
  192. #endif
  193. #if defined(O_CREAT) && !defined(OPENSSL_NO_POSIX_IO) && \
  194. !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS)
  195. {
  196. # ifndef O_BINARY
  197. # define O_BINARY 0
  198. # endif
  199. /*
  200. * chmod(..., 0600) is too late to protect the file, permissions
  201. * should be restrictive from the start
  202. */
  203. int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600);
  204. if (fd != -1)
  205. out = fdopen(fd, "wb");
  206. }
  207. #endif
  208. #ifdef OPENSSL_SYS_VMS
  209. /*
  210. * VMS NOTE: Prior versions of this routine created a _new_ version of
  211. * the rand file for each call into this routine, then deleted all
  212. * existing versions named ;-1, and finally renamed the current version
  213. * as ';1'. Under concurrent usage, this resulted in an RMS race
  214. * condition in rename() which could orphan files (see vms message help
  215. * for RMS$_REENT). With the fopen() calls below, openssl/VMS now shares
  216. * the top-level version of the rand file. Note that there may still be
  217. * conditions where the top-level rand file is locked. If so, this code
  218. * will then create a new version of the rand file. Without the delete
  219. * and rename code, this can result in ascending file versions that stop
  220. * at version 32767, and this routine will then return an error. The
  221. * remedy for this is to recode the calling application to avoid
  222. * concurrent use of the rand file, or synchronize usage at the
  223. * application level. Also consider whether or not you NEED a persistent
  224. * rand file in a concurrent use situation.
  225. */
  226. out = openssl_fopen(file, "rb+");
  227. #endif
  228. if (out == NULL)
  229. out = openssl_fopen(file, "wb");
  230. if (out == NULL)
  231. goto err;
  232. #if !defined(NO_CHMOD) && !defined(OPENSSL_NO_POSIX_IO)
  233. chmod(file, 0600);
  234. #endif
  235. n = RAND_DATA;
  236. for (;;) {
  237. i = (n > BUFSIZE) ? BUFSIZE : n;
  238. n -= BUFSIZE;
  239. if (RAND_bytes(buf, i) <= 0)
  240. rand_err = 1;
  241. i = fwrite(buf, 1, i, out);
  242. if (i <= 0) {
  243. ret = 0;
  244. break;
  245. }
  246. ret += i;
  247. if (n <= 0)
  248. break;
  249. }
  250. fclose(out);
  251. OPENSSL_cleanse(buf, BUFSIZE);
  252. err:
  253. return (rand_err ? -1 : ret);
  254. }
  255. const char *RAND_file_name(char *buf, size_t size)
  256. {
  257. char *s = NULL;
  258. int use_randfile = 1;
  259. #ifdef __OpenBSD__
  260. struct stat sb;
  261. #endif
  262. #if defined(_WIN32) && defined(CP_UTF8)
  263. DWORD len;
  264. WCHAR *var, *val;
  265. if ((var = L"RANDFILE",
  266. len = GetEnvironmentVariableW(var, NULL, 0)) == 0
  267. && (var = L"HOME", use_randfile = 0,
  268. len = GetEnvironmentVariableW(var, NULL, 0)) == 0
  269. && (var = L"USERPROFILE",
  270. len = GetEnvironmentVariableW(var, NULL, 0)) == 0) {
  271. var = L"SYSTEMROOT",
  272. len = GetEnvironmentVariableW(var, NULL, 0);
  273. }
  274. if (len != 0) {
  275. int sz;
  276. val = _alloca(len * sizeof(WCHAR));
  277. if (GetEnvironmentVariableW(var, val, len) < len
  278. && (sz = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0,
  279. NULL, NULL)) != 0) {
  280. s = _alloca(sz);
  281. if (WideCharToMultiByte(CP_UTF8, 0, val, -1, s, sz,
  282. NULL, NULL) == 0)
  283. s = NULL;
  284. }
  285. }
  286. #else
  287. if (OPENSSL_issetugid() != 0) {
  288. use_randfile = 0;
  289. } else {
  290. s = getenv("RANDFILE");
  291. if (s == NULL || *s == '\0') {
  292. use_randfile = 0;
  293. s = getenv("HOME");
  294. }
  295. }
  296. #endif
  297. #ifdef DEFAULT_HOME
  298. if (!use_randfile && s == NULL) {
  299. s = DEFAULT_HOME;
  300. }
  301. #endif
  302. if (s != NULL && *s) {
  303. size_t len = strlen(s);
  304. if (use_randfile && len + 1 < size) {
  305. if (OPENSSL_strlcpy(buf, s, size) >= size)
  306. return NULL;
  307. } else if (len + strlen(RFILE) + 2 < size) {
  308. OPENSSL_strlcpy(buf, s, size);
  309. #ifndef OPENSSL_SYS_VMS
  310. OPENSSL_strlcat(buf, "/", size);
  311. #endif
  312. OPENSSL_strlcat(buf, RFILE, size);
  313. }
  314. } else {
  315. buf[0] = '\0'; /* no file name */
  316. }
  317. #ifdef __OpenBSD__
  318. /*
  319. * given that all random loads just fail if the file can't be seen on a
  320. * stat, we stat the file we're returning, if it fails, use /dev/arandom
  321. * instead. this allows the user to use their own source for good random
  322. * data, but defaults to something hopefully decent if that isn't
  323. * available.
  324. */
  325. if (!buf[0] || stat(buf, &sb) == -1)
  326. if (OPENSSL_strlcpy(buf, "/dev/arandom", size) >= size) {
  327. return NULL;
  328. }
  329. #endif
  330. return buf[0] ? buf : NULL;
  331. }