1 | /* |
2 | * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved |
4 | * |
5 | * Licensed under the Apache License 2.0 (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 |
9 | */ |
10 | |
11 | #include "e_os.h" |
12 | #include "crypto/cryptlib.h" |
13 | #include <openssl/safestack.h> |
14 | |
15 | #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ |
16 | defined(__x86_64) || defined(__x86_64__) || \ |
17 | defined(_M_AMD64) || defined(_M_X64) |
18 | |
19 | extern unsigned int OPENSSL_ia32cap_P[4]; |
20 | |
21 | # if defined(OPENSSL_CPUID_OBJ) |
22 | |
23 | /* |
24 | * Purpose of these minimalistic and character-type-agnostic subroutines |
25 | * is to break dependency on MSVCRT (on Windows) and locale. This makes |
26 | * OPENSSL_cpuid_setup safe to use as "constructor". "Character-type- |
27 | * agnostic" means that they work with either wide or 8-bit characters, |
28 | * exploiting the fact that first 127 characters can be simply casted |
29 | * between the sets, while the rest would be simply rejected by ossl_is* |
30 | * subroutines. |
31 | */ |
32 | # ifdef _WIN32 |
33 | typedef WCHAR variant_char; |
34 | |
35 | static variant_char *ossl_getenv(const char *name) |
36 | { |
37 | /* |
38 | * Since we pull only one environment variable, it's simpler to |
39 | * to just ignore |name| and use equivalent wide-char L-literal. |
40 | * As well as to ignore excessively long values... |
41 | */ |
42 | static WCHAR value[48]; |
43 | DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap" , value, 48); |
44 | |
45 | return (len > 0 && len < 48) ? value : NULL; |
46 | } |
47 | # else |
48 | typedef char variant_char; |
49 | # define ossl_getenv getenv |
50 | # endif |
51 | |
52 | # include "crypto/ctype.h" |
53 | |
54 | static int todigit(variant_char c) |
55 | { |
56 | if (ossl_isdigit(c)) |
57 | return c - '0'; |
58 | else if (ossl_isxdigit(c)) |
59 | return ossl_tolower(c) - 'a' + 10; |
60 | |
61 | /* return largest base value to make caller terminate the loop */ |
62 | return 16; |
63 | } |
64 | |
65 | static uint64_t ossl_strtouint64(const variant_char *str) |
66 | { |
67 | uint64_t ret = 0; |
68 | unsigned int digit, base = 10; |
69 | |
70 | if (*str == '0') { |
71 | base = 8, str++; |
72 | if (ossl_tolower(*str) == 'x') |
73 | base = 16, str++; |
74 | } |
75 | |
76 | while((digit = todigit(*str++)) < base) |
77 | ret = ret * base + digit; |
78 | |
79 | return ret; |
80 | } |
81 | |
82 | static variant_char *ossl_strchr(const variant_char *str, char srch) |
83 | { variant_char c; |
84 | |
85 | while((c = *str)) { |
86 | if (c == srch) |
87 | return (variant_char *)str; |
88 | str++; |
89 | } |
90 | |
91 | return NULL; |
92 | } |
93 | |
94 | # define OPENSSL_CPUID_SETUP |
95 | typedef uint64_t IA32CAP; |
96 | |
97 | void OPENSSL_cpuid_setup(void) |
98 | { |
99 | static int trigger = 0; |
100 | IA32CAP OPENSSL_ia32_cpuid(unsigned int *); |
101 | IA32CAP vec; |
102 | const variant_char *env; |
103 | |
104 | if (trigger) |
105 | return; |
106 | |
107 | trigger = 1; |
108 | if ((env = ossl_getenv("OPENSSL_ia32cap" )) != NULL) { |
109 | int off = (env[0] == '~') ? 1 : 0; |
110 | |
111 | vec = ossl_strtouint64(env + off); |
112 | |
113 | if (off) { |
114 | IA32CAP mask = vec; |
115 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask; |
116 | if (mask & (1<<24)) { |
117 | /* |
118 | * User disables FXSR bit, mask even other capabilities |
119 | * that operate exclusively on XMM, so we don't have to |
120 | * double-check all the time. We mask PCLMULQDQ, AMD XOP, |
121 | * AES-NI and AVX. Formally speaking we don't have to |
122 | * do it in x86_64 case, but we can safely assume that |
123 | * x86_64 users won't actually flip this flag. |
124 | */ |
125 | vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32); |
126 | } |
127 | } else if (env[0] == ':') { |
128 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); |
129 | } |
130 | |
131 | if ((env = ossl_strchr(env, ':')) != NULL) { |
132 | IA32CAP vecx; |
133 | |
134 | env++; |
135 | off = (env[0] == '~') ? 1 : 0; |
136 | vecx = ossl_strtouint64(env + off); |
137 | if (off) { |
138 | OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; |
139 | OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); |
140 | } else { |
141 | OPENSSL_ia32cap_P[2] = (unsigned int)vecx; |
142 | OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); |
143 | } |
144 | } else { |
145 | OPENSSL_ia32cap_P[2] = 0; |
146 | OPENSSL_ia32cap_P[3] = 0; |
147 | } |
148 | } else { |
149 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); |
150 | } |
151 | |
152 | /* |
153 | * |(1<<10) sets a reserved bit to signal that variable |
154 | * was initialized already... This is to avoid interference |
155 | * with cpuid snippets in ELF .init segment. |
156 | */ |
157 | OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); |
158 | OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); |
159 | } |
160 | # else |
161 | unsigned int OPENSSL_ia32cap_P[4]; |
162 | # endif |
163 | #endif |
164 | #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ) |
165 | void OPENSSL_cpuid_setup(void) |
166 | { |
167 | } |
168 | #endif |
169 | |
170 | #if defined(_WIN32) |
171 | # include <tchar.h> |
172 | # include <signal.h> |
173 | # ifdef __WATCOMC__ |
174 | # if defined(_UNICODE) || defined(__UNICODE__) |
175 | # define _vsntprintf _vsnwprintf |
176 | # else |
177 | # define _vsntprintf _vsnprintf |
178 | # endif |
179 | # endif |
180 | # ifdef _MSC_VER |
181 | # define alloca _alloca |
182 | # endif |
183 | |
184 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 |
185 | # ifdef OPENSSL_SYS_WIN_CORE |
186 | |
187 | int OPENSSL_isservice(void) |
188 | { |
189 | /* OneCore API cannot interact with GUI */ |
190 | return 1; |
191 | } |
192 | # else |
193 | int OPENSSL_isservice(void) |
194 | { |
195 | HWINSTA h; |
196 | DWORD len; |
197 | WCHAR *name; |
198 | static union { |
199 | void *p; |
200 | FARPROC f; |
201 | } _OPENSSL_isservice = { |
202 | NULL |
203 | }; |
204 | |
205 | if (_OPENSSL_isservice.p == NULL) { |
206 | HANDLE mod = GetModuleHandle(NULL); |
207 | FARPROC f = NULL; |
208 | |
209 | if (mod != NULL) |
210 | f = GetProcAddress(mod, "_OPENSSL_isservice" ); |
211 | if (f == NULL) |
212 | _OPENSSL_isservice.p = (void *)-1; |
213 | else |
214 | _OPENSSL_isservice.f = f; |
215 | } |
216 | |
217 | if (_OPENSSL_isservice.p != (void *)-1) |
218 | return (*_OPENSSL_isservice.f) (); |
219 | |
220 | h = GetProcessWindowStation(); |
221 | if (h == NULL) |
222 | return -1; |
223 | |
224 | if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || |
225 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) |
226 | return -1; |
227 | |
228 | if (len > 512) |
229 | return -1; /* paranoia */ |
230 | len++, len &= ~1; /* paranoia */ |
231 | name = (WCHAR *)alloca(len + sizeof(WCHAR)); |
232 | if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) |
233 | return -1; |
234 | |
235 | len++, len &= ~1; /* paranoia */ |
236 | name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ |
237 | # if 1 |
238 | /* |
239 | * This doesn't cover "interactive" services [working with real |
240 | * WinSta0's] nor programs started non-interactively by Task Scheduler |
241 | * [those are working with SAWinSta]. |
242 | */ |
243 | if (wcsstr(name, L"Service-0x" )) |
244 | return 1; |
245 | # else |
246 | /* This covers all non-interactive programs such as services. */ |
247 | if (!wcsstr(name, L"WinSta0" )) |
248 | return 1; |
249 | # endif |
250 | else |
251 | return 0; |
252 | } |
253 | # endif |
254 | # else |
255 | int OPENSSL_isservice(void) |
256 | { |
257 | return 0; |
258 | } |
259 | # endif |
260 | |
261 | void OPENSSL_showfatal(const char *fmta, ...) |
262 | { |
263 | va_list ap; |
264 | TCHAR buf[256]; |
265 | const TCHAR *fmt; |
266 | /* |
267 | * First check if it's a console application, in which case the |
268 | * error message would be printed to standard error. |
269 | * Windows CE does not have a concept of a console application, |
270 | * so we need to guard the check. |
271 | */ |
272 | # ifdef STD_ERROR_HANDLE |
273 | HANDLE h; |
274 | |
275 | if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && |
276 | GetFileType(h) != FILE_TYPE_UNKNOWN) { |
277 | /* must be console application */ |
278 | int len; |
279 | DWORD out; |
280 | |
281 | va_start(ap, fmta); |
282 | len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); |
283 | WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); |
284 | va_end(ap); |
285 | return; |
286 | } |
287 | # endif |
288 | |
289 | if (sizeof(TCHAR) == sizeof(char)) |
290 | fmt = (const TCHAR *)fmta; |
291 | else |
292 | do { |
293 | int keepgoing; |
294 | size_t len_0 = strlen(fmta) + 1, i; |
295 | WCHAR *fmtw; |
296 | |
297 | fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); |
298 | if (fmtw == NULL) { |
299 | fmt = (const TCHAR *)L"no stack?" ; |
300 | break; |
301 | } |
302 | if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) |
303 | for (i = 0; i < len_0; i++) |
304 | fmtw[i] = (WCHAR)fmta[i]; |
305 | for (i = 0; i < len_0; i++) { |
306 | if (fmtw[i] == L'%') |
307 | do { |
308 | keepgoing = 0; |
309 | switch (fmtw[i + 1]) { |
310 | case L'0': |
311 | case L'1': |
312 | case L'2': |
313 | case L'3': |
314 | case L'4': |
315 | case L'5': |
316 | case L'6': |
317 | case L'7': |
318 | case L'8': |
319 | case L'9': |
320 | case L'.': |
321 | case L'*': |
322 | case L'-': |
323 | i++; |
324 | keepgoing = 1; |
325 | break; |
326 | case L's': |
327 | fmtw[i + 1] = L'S'; |
328 | break; |
329 | case L'S': |
330 | fmtw[i + 1] = L's'; |
331 | break; |
332 | case L'c': |
333 | fmtw[i + 1] = L'C'; |
334 | break; |
335 | case L'C': |
336 | fmtw[i + 1] = L'c'; |
337 | break; |
338 | } |
339 | } while (keepgoing); |
340 | } |
341 | fmt = (const TCHAR *)fmtw; |
342 | } while (0); |
343 | |
344 | va_start(ap, fmta); |
345 | _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); |
346 | buf[OSSL_NELEM(buf) - 1] = _T('\0'); |
347 | va_end(ap); |
348 | |
349 | # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 |
350 | # ifdef OPENSSL_SYS_WIN_CORE |
351 | /* ONECORE is always NONGUI and NT >= 0x0601 */ |
352 | |
353 | /* |
354 | * TODO: (For non GUI and no std error cases) |
355 | * Add event logging feature here. |
356 | */ |
357 | |
358 | # if !defined(NDEBUG) |
359 | /* |
360 | * We are in a situation where we tried to report a critical |
361 | * error and this failed for some reason. As a last resort, |
362 | * in debug builds, send output to the debugger or any other |
363 | * tool like DebugView which can monitor the output. |
364 | */ |
365 | OutputDebugString(buf); |
366 | # endif |
367 | # else |
368 | /* this -------------v--- guards NT-specific calls */ |
369 | if (check_winnt() && OPENSSL_isservice() > 0) { |
370 | HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL" )); |
371 | |
372 | if (hEventLog != NULL) { |
373 | const TCHAR *pmsg = buf; |
374 | |
375 | if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, |
376 | 1, 0, &pmsg, NULL)) { |
377 | # if !defined(NDEBUG) |
378 | /* |
379 | * We are in a situation where we tried to report a critical |
380 | * error and this failed for some reason. As a last resort, |
381 | * in debug builds, send output to the debugger or any other |
382 | * tool like DebugView which can monitor the output. |
383 | */ |
384 | OutputDebugString(pmsg); |
385 | # endif |
386 | } |
387 | |
388 | (void)DeregisterEventSource(hEventLog); |
389 | } |
390 | } else { |
391 | MessageBox(NULL, buf, _T("OpenSSL: FATAL" ), MB_OK | MB_ICONERROR); |
392 | } |
393 | # endif |
394 | # else |
395 | MessageBox(NULL, buf, _T("OpenSSL: FATAL" ), MB_OK | MB_ICONERROR); |
396 | # endif |
397 | } |
398 | #else |
399 | void OPENSSL_showfatal(const char *fmta, ...) |
400 | { |
401 | #ifndef OPENSSL_NO_STDIO |
402 | va_list ap; |
403 | |
404 | va_start(ap, fmta); |
405 | vfprintf(stderr, fmta, ap); |
406 | va_end(ap); |
407 | #endif |
408 | } |
409 | |
410 | int OPENSSL_isservice(void) |
411 | { |
412 | return 0; |
413 | } |
414 | #endif |
415 | |
416 | void OPENSSL_die(const char *message, const char *file, int line) |
417 | { |
418 | OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n" , |
419 | file, line, message); |
420 | #if !defined(_WIN32) |
421 | abort(); |
422 | #else |
423 | /* |
424 | * Win32 abort() customarily shows a dialog, but we just did that... |
425 | */ |
426 | # if !defined(_WIN32_WCE) |
427 | raise(SIGABRT); |
428 | # endif |
429 | _exit(3); |
430 | #endif |
431 | } |
432 | |
433 | #if !defined(OPENSSL_CPUID_OBJ) |
434 | /* |
435 | * The volatile is used to to ensure that the compiler generates code that reads |
436 | * all values from the array and doesn't try to optimize this away. The standard |
437 | * doesn't actually require this behavior if the original data pointed to is |
438 | * not volatile, but compilers do this in practice anyway. |
439 | * |
440 | * There are also assembler versions of this function. |
441 | */ |
442 | # undef CRYPTO_memcmp |
443 | int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) |
444 | { |
445 | size_t i; |
446 | const volatile unsigned char *a = in_a; |
447 | const volatile unsigned char *b = in_b; |
448 | unsigned char x = 0; |
449 | |
450 | for (i = 0; i < len; i++) |
451 | x |= a[i] ^ b[i]; |
452 | |
453 | return x; |
454 | } |
455 | |
456 | /* |
457 | * For systems that don't provide an instruction counter register or equivalent. |
458 | */ |
459 | uint32_t OPENSSL_rdtsc(void) |
460 | { |
461 | return 0; |
462 | } |
463 | |
464 | size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt) |
465 | { |
466 | return 0; |
467 | } |
468 | |
469 | size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) |
470 | { |
471 | return 0; |
472 | } |
473 | #endif |
474 | |