/src/openssl/crypto/cryptlib.c
Line | Count | Source (jump to first uncovered line) |
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 | 1.11k | # define ossl_getenv getenv |
50 | | # endif |
51 | | |
52 | | # include "crypto/ctype.h" |
53 | | |
54 | | static int todigit(variant_char c) |
55 | 0 | { |
56 | 0 | if (ossl_isdigit(c)) |
57 | 0 | return c - '0'; |
58 | 0 | else if (ossl_isxdigit(c)) |
59 | 0 | return ossl_tolower(c) - 'a' + 10; |
60 | | |
61 | | /* return largest base value to make caller terminate the loop */ |
62 | 0 | return 16; |
63 | 0 | } |
64 | | |
65 | | static uint64_t ossl_strtouint64(const variant_char *str) |
66 | 0 | { |
67 | 0 | uint64_t ret = 0; |
68 | 0 | unsigned int digit, base = 10; |
69 | |
|
70 | 0 | if (*str == '0') { |
71 | 0 | base = 8, str++; |
72 | 0 | if (ossl_tolower(*str) == 'x') |
73 | 0 | base = 16, str++; |
74 | 0 | } |
75 | |
|
76 | 0 | while((digit = todigit(*str++)) < base) |
77 | 0 | ret = ret * base + digit; |
78 | |
|
79 | 0 | return ret; |
80 | 0 | } |
81 | | |
82 | | static variant_char *ossl_strchr(const variant_char *str, char srch) |
83 | 0 | { variant_char c; |
84 | |
|
85 | 0 | while((c = *str)) { |
86 | 0 | if (c == srch) |
87 | 0 | return (variant_char *)str; |
88 | 0 | str++; |
89 | 0 | } |
90 | | |
91 | 0 | return NULL; |
92 | 0 | } |
93 | | |
94 | | # define OPENSSL_CPUID_SETUP |
95 | | typedef uint64_t IA32CAP; |
96 | | |
97 | | void OPENSSL_cpuid_setup(void) |
98 | 2.22k | { |
99 | 2.22k | static int trigger = 0; |
100 | 2.22k | IA32CAP OPENSSL_ia32_cpuid(unsigned int *); |
101 | 2.22k | IA32CAP vec; |
102 | 2.22k | const variant_char *env; |
103 | | |
104 | 2.22k | if (trigger) |
105 | 1.11k | return; |
106 | | |
107 | 1.11k | trigger = 1; |
108 | 1.11k | if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) { |
109 | 0 | int off = (env[0] == '~') ? 1 : 0; |
110 | |
|
111 | 0 | vec = ossl_strtouint64(env + off); |
112 | |
|
113 | 0 | if (off) { |
114 | 0 | IA32CAP mask = vec; |
115 | 0 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask; |
116 | 0 | 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 | 0 | vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32); |
126 | 0 | } |
127 | 0 | } else if (env[0] == ':') { |
128 | 0 | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); |
129 | 0 | } |
130 | |
|
131 | 0 | if ((env = ossl_strchr(env, ':')) != NULL) { |
132 | 0 | IA32CAP vecx; |
133 | |
|
134 | 0 | env++; |
135 | 0 | off = (env[0] == '~') ? 1 : 0; |
136 | 0 | vecx = ossl_strtouint64(env + off); |
137 | 0 | if (off) { |
138 | 0 | OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; |
139 | 0 | OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); |
140 | 0 | } else { |
141 | 0 | OPENSSL_ia32cap_P[2] = (unsigned int)vecx; |
142 | 0 | OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); |
143 | 0 | } |
144 | 0 | } else { |
145 | 0 | OPENSSL_ia32cap_P[2] = 0; |
146 | 0 | OPENSSL_ia32cap_P[3] = 0; |
147 | 0 | } |
148 | 1.11k | } else { |
149 | 1.11k | vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); |
150 | 1.11k | } |
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 | 1.11k | OPENSSL_ia32cap_P[0] = (unsigned int)vec | (1 << 10); |
158 | 1.11k | OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); |
159 | 1.11k | } |
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 | 0 | { |
401 | 0 | #ifndef OPENSSL_NO_STDIO |
402 | 0 | va_list ap; |
403 | |
|
404 | 0 | va_start(ap, fmta); |
405 | 0 | vfprintf(stderr, fmta, ap); |
406 | 0 | va_end(ap); |
407 | 0 | #endif |
408 | 0 | } |
409 | | |
410 | | int OPENSSL_isservice(void) |
411 | 0 | { |
412 | 0 | return 0; |
413 | 0 | } |
414 | | #endif |
415 | | |
416 | | void OPENSSL_die(const char *message, const char *file, int line) |
417 | 0 | { |
418 | 0 | OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", |
419 | 0 | file, line, message); |
420 | 0 | #if !defined(_WIN32) |
421 | 0 | 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 | 0 | } |
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 |