]>
Commit | Line | Data |
---|---|---|
d2e9e320 RS |
1 | /* |
2 | * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. | |
aa8f3d76 | 3 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
19b8d06a | 4 | * |
d2e9e320 RS |
5 | * Licensed under the OpenSSL license (the "License"). You may not use |
6 | * this file except in compliance with the License. You can obtain a copy | |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
19b8d06a | 9 | */ |
d2e9e320 | 10 | |
7b9f8f7f | 11 | #include "internal/cryptlib_int.h" |
c7922304 | 12 | #include <openssl/safestack.h> |
d02b48c6 | 13 | |
0f113f3e | 14 | #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ |
0f113f3e MC |
15 | defined(__x86_64) || defined(__x86_64__) || \ |
16 | defined(_M_AMD64) || defined(_M_X64) | |
14e21f86 | 17 | |
0f113f3e | 18 | extern unsigned int OPENSSL_ia32cap_P[4]; |
14e21f86 | 19 | |
0f113f3e | 20 | # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) |
984d6c60 | 21 | #include <stdio.h> |
0f113f3e | 22 | # define OPENSSL_CPUID_SETUP |
1c7b2c0e | 23 | typedef uint64_t IA32CAP; |
2b247cf8 | 24 | void OPENSSL_cpuid_setup(void) |
0f113f3e MC |
25 | { |
26 | static int trigger = 0; | |
27 | IA32CAP OPENSSL_ia32_cpuid(unsigned int *); | |
28 | IA32CAP vec; | |
29 | char *env; | |
30 | ||
31 | if (trigger) | |
32 | return; | |
33 | ||
34 | trigger = 1; | |
35 | if ((env = getenv("OPENSSL_ia32cap"))) { | |
36 | int off = (env[0] == '~') ? 1 : 0; | |
37 | # if defined(_WIN32) | |
38 | if (!sscanf(env + off, "%I64i", &vec)) | |
39 | vec = strtoul(env + off, NULL, 0); | |
40 | # else | |
41 | if (!sscanf(env + off, "%lli", (long long *)&vec)) | |
42 | vec = strtoul(env + off, NULL, 0); | |
43 | # endif | |
44 | if (off) | |
45 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~vec; | |
46 | else if (env[0] == ':') | |
47 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); | |
48 | ||
49 | OPENSSL_ia32cap_P[2] = 0; | |
50 | if ((env = strchr(env, ':'))) { | |
51 | unsigned int vecx; | |
52 | env++; | |
53 | off = (env[0] == '~') ? 1 : 0; | |
54 | vecx = strtoul(env + off, NULL, 0); | |
55 | if (off) | |
56 | OPENSSL_ia32cap_P[2] &= ~vecx; | |
57 | else | |
58 | OPENSSL_ia32cap_P[2] = vecx; | |
59 | } | |
60 | } else | |
61 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); | |
e303f55f | 62 | |
14e21f86 AP |
63 | /* |
64 | * |(1<<10) sets a reserved bit to signal that variable | |
65 | * was initialized already... This is to avoid interference | |
66 | * with cpuid snippets in ELF .init segment. | |
67 | */ | |
0f113f3e MC |
68 | OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); |
69 | OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); | |
14e21f86 | 70 | } |
0f113f3e | 71 | # else |
c5cd28bd | 72 | unsigned int OPENSSL_ia32cap_P[4]; |
0f113f3e | 73 | # endif |
14e21f86 | 74 | #endif |
1875e6db | 75 | int OPENSSL_NONPIC_relocated = 0; |
a00e414f | 76 | #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) |
0f113f3e MC |
77 | void OPENSSL_cpuid_setup(void) |
78 | { | |
79 | } | |
14e21f86 AP |
80 | #endif |
81 | ||
0f113f3e MC |
82 | #if defined(_WIN32) && !defined(__CYGWIN__) |
83 | # include <tchar.h> | |
84 | # include <signal.h> | |
85 | # ifdef __WATCOMC__ | |
86 | # if defined(_UNICODE) || defined(__UNICODE__) | |
87 | # define _vsntprintf _vsnwprintf | |
88 | # else | |
89 | # define _vsntprintf _vsnprintf | |
90 | # endif | |
91 | # endif | |
92 | # ifdef _MSC_VER | |
93 | # define alloca _alloca | |
94 | # endif | |
95 | ||
96 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
e476f942 | 97 | int OPENSSL_isservice(void) |
0f113f3e MC |
98 | { |
99 | HWINSTA h; | |
100 | DWORD len; | |
101 | WCHAR *name; | |
102 | static union { | |
103 | void *p; | |
156561b0 | 104 | FARPROC f; |
0f113f3e MC |
105 | } _OPENSSL_isservice = { |
106 | NULL | |
107 | }; | |
471d0eb3 AP |
108 | |
109 | if (_OPENSSL_isservice.p == NULL) { | |
156561b0 AP |
110 | HANDLE mod = GetModuleHandle(NULL); |
111 | if (mod != NULL) | |
112 | _OPENSSL_isservice.f = GetProcAddress(mod, "_OPENSSL_isservice"); | |
0f113f3e MC |
113 | if (_OPENSSL_isservice.p == NULL) |
114 | _OPENSSL_isservice.p = (void *)-1; | |
471d0eb3 AP |
115 | } |
116 | ||
117 | if (_OPENSSL_isservice.p != (void *)-1) | |
0f113f3e | 118 | return (*_OPENSSL_isservice.f) (); |
9f2027e5 | 119 | |
9f2027e5 | 120 | h = GetProcessWindowStation(); |
0f113f3e MC |
121 | if (h == NULL) |
122 | return -1; | |
123 | ||
124 | if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || | |
125 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) | |
126 | return -1; | |
127 | ||
128 | if (len > 512) | |
129 | return -1; /* paranoia */ | |
130 | len++, len &= ~1; /* paranoia */ | |
131 | name = (WCHAR *)alloca(len + sizeof(WCHAR)); | |
132 | if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) | |
133 | return -1; | |
134 | ||
135 | len++, len &= ~1; /* paranoia */ | |
136 | name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ | |
137 | # if 1 | |
138 | /* | |
139 | * This doesn't cover "interactive" services [working with real | |
140 | * WinSta0's] nor programs started non-interactively by Task Scheduler | |
141 | * [those are working with SAWinSta]. | |
142 | */ | |
143 | if (wcsstr(name, L"Service-0x")) | |
144 | return 1; | |
145 | # else | |
9f2027e5 | 146 | /* This covers all non-interactive programs such as services. */ |
0f113f3e MC |
147 | if (!wcsstr(name, L"WinSta0")) |
148 | return 1; | |
149 | # endif | |
150 | else | |
151 | return 0; | |
9f2027e5 | 152 | } |
0f113f3e MC |
153 | # else |
154 | int OPENSSL_isservice(void) | |
155 | { | |
156 | return 0; | |
157 | } | |
158 | # endif | |
159 | ||
160 | void OPENSSL_showfatal(const char *fmta, ...) | |
161 | { | |
162 | va_list ap; | |
163 | TCHAR buf[256]; | |
164 | const TCHAR *fmt; | |
2f0ca54c EK |
165 | /* |
166 | * First check if it's a console application, in which case the | |
167 | * error message would be printed to standard error. | |
168 | * Windows CE does not have a concept of a console application, | |
169 | * so we need to guard the check. | |
170 | */ | |
171 | # ifdef STD_ERROR_HANDLE | |
0f113f3e MC |
172 | HANDLE h; |
173 | ||
174 | if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && | |
175 | GetFileType(h) != FILE_TYPE_UNKNOWN) { | |
176 | /* must be console application */ | |
177 | int len; | |
178 | DWORD out; | |
179 | ||
180 | va_start(ap, fmta); | |
181 | len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); | |
182 | WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); | |
183 | va_end(ap); | |
184 | return; | |
9f2027e5 | 185 | } |
0f113f3e | 186 | # endif |
9f2027e5 | 187 | |
0f113f3e MC |
188 | if (sizeof(TCHAR) == sizeof(char)) |
189 | fmt = (const TCHAR *)fmta; | |
9f2027e5 | 190 | else |
0f113f3e MC |
191 | do { |
192 | int keepgoing; | |
193 | size_t len_0 = strlen(fmta) + 1, i; | |
194 | WCHAR *fmtw; | |
195 | ||
196 | fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); | |
197 | if (fmtw == NULL) { | |
198 | fmt = (const TCHAR *)L"no stack?"; | |
199 | break; | |
200 | } | |
0f113f3e | 201 | if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) |
0f113f3e MC |
202 | for (i = 0; i < len_0; i++) |
203 | fmtw[i] = (WCHAR)fmta[i]; | |
0f113f3e MC |
204 | for (i = 0; i < len_0; i++) { |
205 | if (fmtw[i] == L'%') | |
206 | do { | |
207 | keepgoing = 0; | |
208 | switch (fmtw[i + 1]) { | |
209 | case L'0': | |
210 | case L'1': | |
211 | case L'2': | |
212 | case L'3': | |
213 | case L'4': | |
214 | case L'5': | |
215 | case L'6': | |
216 | case L'7': | |
217 | case L'8': | |
218 | case L'9': | |
219 | case L'.': | |
220 | case L'*': | |
221 | case L'-': | |
222 | i++; | |
223 | keepgoing = 1; | |
224 | break; | |
225 | case L's': | |
226 | fmtw[i + 1] = L'S'; | |
227 | break; | |
228 | case L'S': | |
229 | fmtw[i + 1] = L's'; | |
230 | break; | |
231 | case L'c': | |
232 | fmtw[i + 1] = L'C'; | |
233 | break; | |
234 | case L'C': | |
235 | fmtw[i + 1] = L'c'; | |
236 | break; | |
237 | } | |
238 | } while (keepgoing); | |
239 | } | |
240 | fmt = (const TCHAR *)fmtw; | |
241 | } while (0); | |
242 | ||
243 | va_start(ap, fmta); | |
bdcb1a2c DSH |
244 | _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); |
245 | buf[OSSL_NELEM(buf) - 1] = _T('\0'); | |
0f113f3e MC |
246 | va_end(ap); |
247 | ||
248 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 | |
249 | /* this -------------v--- guards NT-specific calls */ | |
250 | if (check_winnt() && OPENSSL_isservice() > 0) { | |
4cd94416 GK |
251 | HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); |
252 | ||
253 | if (hEventLog != NULL) { | |
254 | const TCHAR *pmsg = buf; | |
255 | ||
256 | if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, | |
257 | 1, 0, &pmsg, NULL)) { | |
258 | #if defined(DEBUG) | |
259 | /* | |
260 | * We are in a situation where we tried to report a critical | |
261 | * error and this failed for some reason. As a last resort, | |
262 | * in debug builds, send output to the debugger or any other | |
263 | * tool like DebugView which can monitor the output. | |
264 | */ | |
265 | OutputDebugString(pmsg); | |
266 | #endif | |
267 | } | |
268 | ||
269 | (void)DeregisterEventSource(hEventLog); | |
270 | } | |
0f113f3e MC |
271 | } else |
272 | # endif | |
4cd94416 | 273 | MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); |
9f2027e5 AP |
274 | } |
275 | #else | |
0f113f3e MC |
276 | void OPENSSL_showfatal(const char *fmta, ...) |
277 | { | |
984d6c60 | 278 | #ifndef OPENSSL_NO_STDIO |
0f113f3e MC |
279 | va_list ap; |
280 | ||
281 | va_start(ap, fmta); | |
282 | vfprintf(stderr, fmta, ap); | |
283 | va_end(ap); | |
984d6c60 | 284 | #endif |
0f113f3e | 285 | } |
9f2027e5 | 286 | |
0f113f3e MC |
287 | int OPENSSL_isservice(void) |
288 | { | |
289 | return 0; | |
9f2027e5 AP |
290 | } |
291 | #endif | |
292 | ||
040d43b3 | 293 | void OPENSSL_die(const char *message, const char *file, int line) |
0f113f3e | 294 | { |
040d43b3 RS |
295 | OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", |
296 | file, line, message); | |
6022fe81 | 297 | #if !defined(_WIN32) || defined(__CYGWIN__) |
0f113f3e | 298 | abort(); |
3b58c74c | 299 | #else |
0f113f3e MC |
300 | /* |
301 | * Win32 abort() customarily shows a dialog, but we just did that... | |
302 | */ | |
303 | # if !defined(_WIN32_WCE) | |
304 | raise(SIGABRT); | |
305 | # endif | |
306 | _exit(3); | |
3b58c74c | 307 | #endif |
0f113f3e | 308 | } |
9e88c827 | 309 | |
e33826f0 | 310 | #if !defined(OPENSSL_CPUID_OBJ) |
49791083 KR |
311 | /* |
312 | * The volatile is used to to ensure that the compiler generates code that reads | |
313 | * all values from the array and doesn't try to optimize this away. The standard | |
314 | * doesn't actually require this behavior if the original data pointed to is | |
315 | * not volatile, but compilers do this in practice anyway. | |
316 | * | |
317 | * There are also assembler versions of this function. | |
eb507efb | 318 | */ |
43c56417 | 319 | # undef CRYPTO_memcmp |
49791083 | 320 | int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) |
0f113f3e MC |
321 | { |
322 | size_t i; | |
98ab5764 RS |
323 | const volatile unsigned char *a = in_a; |
324 | const volatile unsigned char *b = in_b; | |
0f113f3e | 325 | unsigned char x = 0; |
7c770d57 | 326 | |
0f113f3e MC |
327 | for (i = 0; i < len; i++) |
328 | x |= a[i] ^ b[i]; | |
7c770d57 | 329 | |
0f113f3e MC |
330 | return x; |
331 | } | |
e33826f0 | 332 | #endif |