VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.7/crypto/rand/randfile.c

最後變更 在這個檔案是 106601,由 vboxsync 提交於 5 月 前

openssl-3.1.7/randfile.c: Build fix for win.arm64 - missing _alloca() proto. jiraref:VBP-1171

檔案大小: 9.8 KB
 
1/*
2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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
10#if defined (__TANDEM) && defined (_SPT_MODEL_)
11/*
12 * These definitions have to come first in SPT due to scoping of the
13 * declarations in c99 associated with SPT use of stat.
14 */
15# include <sys/types.h>
16# include <sys/stat.h>
17#endif
18
19#include "internal/cryptlib.h"
20
21#include <errno.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#ifdef _MSC_VER /* VBox */
26# include <iprt/alloca.h> /* VBox: fix for missing _alloca prototype on win.arm64 */
27#endif /* VBox */
28
29#include <openssl/crypto.h>
30#include <openssl/rand.h>
31#include <openssl/buffer.h>
32
33#ifdef OPENSSL_SYS_VMS
34# include <unixio.h>
35#endif
36#include <sys/types.h>
37#ifndef OPENSSL_NO_POSIX_IO
38# include <sys/stat.h>
39# include <fcntl.h>
40# if defined(_WIN32) && !defined(_WIN32_WCE)
41# ifdef VBOX
42# include <iprt/win/windows.h>
43# else
44# include <windows.h>
45# endif
46# include <io.h>
47# define stat _stat
48# define chmod _chmod
49# define open _open
50# define fdopen _fdopen
51# define fstat _fstat
52# define fileno _fileno
53# endif
54#endif
55
56/*
57 * Following should not be needed, and we could have been stricter
58 * and demand S_IS*. But some systems just don't comply... Formally
59 * below macros are "anatomically incorrect", because normally they
60 * would look like ((m) & MASK == TYPE), but since MASK availability
61 * is as questionable, we settle for this poor-man fallback...
62 */
63# if !defined(S_ISREG)
64# define S_ISREG(m) ((m) & S_IFREG)
65# endif
66
67#define RAND_BUF_SIZE 1024
68#define RFILE ".rnd"
69
70#ifdef OPENSSL_SYS_VMS
71/*
72 * __FILE_ptr32 is a type provided by DEC C headers (types.h specifically)
73 * to make sure the FILE* is a 32-bit pointer no matter what. We know that
74 * stdio functions return this type (a study of stdio.h proves it).
75 *
76 * This declaration is a nasty hack to get around vms' extension to fopen for
77 * passing in sharing options being disabled by /STANDARD=ANSI89
78 */
79static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
80 (__FILE_ptr32 (*)(const char *, const char *, ...))fopen;
81# define VMS_OPEN_ATTRS \
82 "shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0"
83# define openssl_fopen(fname, mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS)
84#endif
85
86/*
87 * Note that these functions are intended for seed files only. Entropy
88 * devices and EGD sockets are handled in rand_unix.c If |bytes| is
89 * -1 read the complete file; otherwise read the specified amount.
90 */
91int RAND_load_file(const char *file, long bytes)
92{
93 /*
94 * The load buffer size exceeds the chunk size by the comfortable amount
95 * of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose
96 * to avoid calling RAND_add() with a small final chunk. Instead, such
97 * a small final chunk will be added together with the previous chunk
98 * (unless it's the only one).
99 */
100#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH)
101 unsigned char buf[RAND_LOAD_BUF_SIZE];
102
103#ifndef OPENSSL_NO_POSIX_IO
104 struct stat sb;
105#endif
106 int i, n, ret = 0;
107 FILE *in;
108
109 if (bytes == 0)
110 return 0;
111
112 if ((in = openssl_fopen(file, "rb")) == NULL) {
113 ERR_raise_data(ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE,
114 "Filename=%s", file);
115 return -1;
116 }
117
118#ifndef OPENSSL_NO_POSIX_IO
119 if (fstat(fileno(in), &sb) < 0) {
120 ERR_raise_data(ERR_LIB_RAND, RAND_R_INTERNAL_ERROR,
121 "Filename=%s", file);
122 fclose(in);
123 return -1;
124 }
125
126 if (bytes < 0) {
127 if (S_ISREG(sb.st_mode))
128 bytes = sb.st_size;
129 else
130 bytes = RAND_DRBG_STRENGTH;
131 }
132#endif
133 /*
134 * On VMS, setbuf() will only take 32-bit pointers, and a compilation
135 * with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
136 * However, we trust that the C RTL will never give us a FILE pointer
137 * above the first 4 GB of memory, so we simply turn off the warning
138 * temporarily.
139 */
140#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
141# pragma environment save
142# pragma message disable maylosedata2
143#endif
144 /*
145 * Don't buffer, because even if |file| is regular file, we have
146 * no control over the buffer, so why would we want a copy of its
147 * contents lying around?
148 */
149 setbuf(in, NULL);
150#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
151# pragma environment restore
152#endif
153
154 for ( ; ; ) {
155 if (bytes > 0)
156 n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE;
157 else
158 n = RAND_LOAD_BUF_SIZE;
159 i = fread(buf, 1, n, in);
160#ifdef EINTR
161 if (ferror(in) && errno == EINTR){
162 clearerr(in);
163 if (i == 0)
164 continue;
165 }
166#endif
167 if (i == 0)
168 break;
169
170 RAND_add(buf, i, (double)i);
171 ret += i;
172
173 /* If given a bytecount, and we did it, break. */
174 if (bytes > 0 && (bytes -= i) <= 0)
175 break;
176 }
177
178 OPENSSL_cleanse(buf, sizeof(buf));
179 fclose(in);
180 if (!RAND_status()) {
181 ERR_raise_data(ERR_LIB_RAND, RAND_R_RESEED_ERROR, "Filename=%s", file);
182 return -1;
183 }
184
185 return ret;
186}
187
188int RAND_write_file(const char *file)
189{
190 unsigned char buf[RAND_BUF_SIZE];
191 int ret = -1;
192 FILE *out = NULL;
193#ifndef OPENSSL_NO_POSIX_IO
194 struct stat sb;
195
196 if (stat(file, &sb) >= 0 && !S_ISREG(sb.st_mode)) {
197 ERR_raise_data(ERR_LIB_RAND, RAND_R_NOT_A_REGULAR_FILE,
198 "Filename=%s", file);
199 return -1;
200 }
201#endif
202
203 /* Collect enough random data. */
204 if (RAND_priv_bytes(buf, (int)sizeof(buf)) != 1)
205 return -1;
206
207#if defined(O_CREAT) && !defined(OPENSSL_NO_POSIX_IO) && \
208 !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS)
209 {
210# ifndef O_BINARY
211# define O_BINARY 0
212# endif
213 /*
214 * chmod(..., 0600) is too late to protect the file, permissions
215 * should be restrictive from the start
216 */
217 int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600);
218 if (fd != -1)
219 out = fdopen(fd, "wb");
220 }
221#endif
222
223#ifdef OPENSSL_SYS_VMS
224 /*
225 * VMS NOTE: Prior versions of this routine created a _new_ version of
226 * the rand file for each call into this routine, then deleted all
227 * existing versions named ;-1, and finally renamed the current version
228 * as ';1'. Under concurrent usage, this resulted in an RMS race
229 * condition in rename() which could orphan files (see vms message help
230 * for RMS$_REENT). With the fopen() calls below, openssl/VMS now shares
231 * the top-level version of the rand file. Note that there may still be
232 * conditions where the top-level rand file is locked. If so, this code
233 * will then create a new version of the rand file. Without the delete
234 * and rename code, this can result in ascending file versions that stop
235 * at version 32767, and this routine will then return an error. The
236 * remedy for this is to recode the calling application to avoid
237 * concurrent use of the rand file, or synchronize usage at the
238 * application level. Also consider whether or not you NEED a persistent
239 * rand file in a concurrent use situation.
240 */
241 out = openssl_fopen(file, "rb+");
242#endif
243
244 if (out == NULL)
245 out = openssl_fopen(file, "wb");
246 if (out == NULL) {
247 ERR_raise_data(ERR_LIB_RAND, RAND_R_CANNOT_OPEN_FILE,
248 "Filename=%s", file);
249 return -1;
250 }
251
252#if !defined(NO_CHMOD) && !defined(OPENSSL_NO_POSIX_IO)
253 /*
254 * Yes it's late to do this (see above comment), but better than nothing.
255 */
256 chmod(file, 0600);
257#endif
258
259 ret = fwrite(buf, 1, RAND_BUF_SIZE, out);
260 fclose(out);
261 OPENSSL_cleanse(buf, RAND_BUF_SIZE);
262 return ret;
263}
264
265const char *RAND_file_name(char *buf, size_t size)
266{
267 char *s = NULL;
268 size_t len;
269 int use_randfile = 1;
270
271#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
272 DWORD envlen;
273 WCHAR *var;
274
275 /* Look up various environment variables. */
276 if ((envlen = GetEnvironmentVariableW(var = L"RANDFILE", NULL, 0)) == 0) {
277 use_randfile = 0;
278 if ((envlen = GetEnvironmentVariableW(var = L"HOME", NULL, 0)) == 0
279 && (envlen = GetEnvironmentVariableW(var = L"USERPROFILE",
280 NULL, 0)) == 0)
281 envlen = GetEnvironmentVariableW(var = L"SYSTEMROOT", NULL, 0);
282 }
283
284 /* If we got a value, allocate space to hold it and then get it. */
285 if (envlen != 0) {
286 int sz;
287 WCHAR *val = _alloca(envlen * sizeof(WCHAR));
288
289 if (GetEnvironmentVariableW(var, val, envlen) < envlen
290 && (sz = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0,
291 NULL, NULL)) != 0) {
292 s = _alloca(sz);
293 if (WideCharToMultiByte(CP_UTF8, 0, val, -1, s, sz,
294 NULL, NULL) == 0)
295 s = NULL;
296 }
297 }
298#else
299 if ((s = ossl_safe_getenv("RANDFILE")) == NULL || *s == '\0') {
300 use_randfile = 0;
301 s = ossl_safe_getenv("HOME");
302 }
303#endif
304
305#ifdef DEFAULT_HOME
306 if (!use_randfile && s == NULL)
307 s = DEFAULT_HOME;
308#endif
309 if (s == NULL || *s == '\0')
310 return NULL;
311
312 len = strlen(s);
313 if (use_randfile) {
314 if (len + 1 >= size)
315 return NULL;
316 strcpy(buf, s);
317 } else {
318 if (len + 1 + strlen(RFILE) + 1 >= size)
319 return NULL;
320 strcpy(buf, s);
321#ifndef OPENSSL_SYS_VMS
322 strcat(buf, "/");
323#endif
324 strcat(buf, RFILE);
325 }
326
327 return buf;
328}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette