2 * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
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
12 #include "crypto/cryptlib.h"
13 #include <openssl/safestack.h>
15 #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
16 defined(__x86_64) || defined(__x86_64__) || \
17 defined(_M_AMD64) || defined(_M_X64)
19 extern unsigned int OPENSSL_ia32cap_P
[4];
21 # if defined(OPENSSL_CPUID_OBJ)
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*
33 typedef WCHAR variant_char
;
35 static variant_char
*ossl_getenv(const char *name
)
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...
42 static WCHAR value
[48];
43 DWORD len
= GetEnvironmentVariableW(L
"OPENSSL_ia32cap", value
, 48);
45 return (len
> 0 && len
< 48) ? value
: NULL
;
48 typedef char variant_char
;
49 # define ossl_getenv getenv
52 # include "crypto/ctype.h"
54 static int todigit(variant_char c
)
58 else if (ossl_isxdigit(c
))
59 return ossl_tolower(c
) - 'a' + 10;
61 /* return largest base value to make caller terminate the loop */
65 static uint64_t ossl_strtouint64(const variant_char
*str
)
68 unsigned int digit
, base
= 10;
72 if (ossl_tolower(*str
) == 'x')
76 while((digit
= todigit(*str
++)) < base
)
77 ret
= ret
* base
+ digit
;
82 static variant_char
*ossl_strchr(const variant_char
*str
, char srch
)
87 return (variant_char
*)str
;
94 # define OPENSSL_CPUID_SETUP
95 typedef uint64_t IA32CAP
;
97 void OPENSSL_cpuid_setup(void)
99 static int trigger
= 0;
100 IA32CAP
OPENSSL_ia32_cpuid(unsigned int *);
102 const variant_char
*env
;
108 if ((env
= ossl_getenv("OPENSSL_ia32cap")) != NULL
) {
109 int off
= (env
[0] == '~') ? 1 : 0;
111 vec
= ossl_strtouint64(env
+ off
);
115 vec
= OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P
) & ~mask
;
116 if (mask
& (1<<24)) {
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.
125 vec
&= ~((IA32CAP
)(1<<1|1<<11|1<<25|1<<28) << 32);
127 } else if (env
[0] == ':') {
128 vec
= OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P
);
131 if ((env
= ossl_strchr(env
, ':')) != NULL
) {
135 off
= (env
[0] == '~') ? 1 : 0;
136 vecx
= ossl_strtouint64(env
+ off
);
138 OPENSSL_ia32cap_P
[2] &= ~(unsigned int)vecx
;
139 OPENSSL_ia32cap_P
[3] &= ~(unsigned int)(vecx
>> 32);
141 OPENSSL_ia32cap_P
[2] = (unsigned int)vecx
;
142 OPENSSL_ia32cap_P
[3] = (unsigned int)(vecx
>> 32);
145 OPENSSL_ia32cap_P
[2] = 0;
146 OPENSSL_ia32cap_P
[3] = 0;
149 vec
= OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P
);
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.
157 OPENSSL_ia32cap_P
[0] = (unsigned int)vec
| (1 << 10);
158 OPENSSL_ia32cap_P
[1] = (unsigned int)(vec
>> 32);
161 unsigned int OPENSSL_ia32cap_P
[4];
164 #if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
165 void OPENSSL_cpuid_setup(void)
174 # if defined(_UNICODE) || defined(__UNICODE__)
175 # define _vsntprintf _vsnwprintf
177 # define _vsntprintf _vsnprintf
181 # define alloca _alloca
184 # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
185 # ifdef OPENSSL_SYS_WIN_CORE
187 int OPENSSL_isservice(void)
189 /* OneCore API cannot interact with GUI */
193 int OPENSSL_isservice(void)
201 } _OPENSSL_isservice
= {
205 if (_OPENSSL_isservice
.p
== NULL
) {
206 HANDLE mod
= GetModuleHandle(NULL
);
210 f
= GetProcAddress(mod
, "_OPENSSL_isservice");
212 _OPENSSL_isservice
.p
= (void *)-1;
214 _OPENSSL_isservice
.f
= f
;
217 if (_OPENSSL_isservice
.p
!= (void *)-1)
218 return (*_OPENSSL_isservice
.f
) ();
220 h
= GetProcessWindowStation();
224 if (GetUserObjectInformationW(h
, UOI_NAME
, NULL
, 0, &len
) ||
225 GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
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
))
235 len
++, len
&= ~1; /* paranoia */
236 name
[len
/ sizeof(WCHAR
)] = L
'\0'; /* paranoia */
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].
243 if (wcsstr(name
, L
"Service-0x"))
246 /* This covers all non-interactive programs such as services. */
247 if (!wcsstr(name
, L
"WinSta0"))
255 int OPENSSL_isservice(void)
261 void OPENSSL_showfatal(const char *fmta
, ...)
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.
272 # ifdef STD_ERROR_HANDLE
275 if ((h
= GetStdHandle(STD_ERROR_HANDLE
)) != NULL
&&
276 GetFileType(h
) != FILE_TYPE_UNKNOWN
) {
277 /* must be console application */
282 len
= _vsnprintf((char *)buf
, sizeof(buf
), fmta
, ap
);
283 WriteFile(h
, buf
, len
< 0 ? sizeof(buf
) : (DWORD
) len
, &out
, NULL
);
289 if (sizeof(TCHAR
) == sizeof(char))
290 fmt
= (const TCHAR
*)fmta
;
294 size_t len_0
= strlen(fmta
) + 1, i
;
297 fmtw
= (WCHAR
*)alloca(len_0
* sizeof(WCHAR
));
299 fmt
= (const TCHAR
*)L
"no stack?";
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
++) {
309 switch (fmtw
[i
+ 1]) {
341 fmt
= (const TCHAR
*)fmtw
;
345 _vsntprintf(buf
, OSSL_NELEM(buf
) - 1, fmt
, ap
);
346 buf
[OSSL_NELEM(buf
) - 1] = _T('\0');
349 # if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333
350 # ifdef OPENSSL_SYS_WIN_CORE
351 /* ONECORE is always NONGUI and NT >= 0x0601 */
354 * TODO: (For non GUI and no std error cases)
355 * Add event logging feature here.
358 # if !defined(NDEBUG)
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.
365 OutputDebugString(buf
);
368 /* this -------------v--- guards NT-specific calls */
369 if (check_winnt() && OPENSSL_isservice() > 0) {
370 HANDLE hEventLog
= RegisterEventSource(NULL
, _T("OpenSSL"));
372 if (hEventLog
!= NULL
) {
373 const TCHAR
*pmsg
= buf
;
375 if (!ReportEvent(hEventLog
, EVENTLOG_ERROR_TYPE
, 0, 0, NULL
,
376 1, 0, &pmsg
, NULL
)) {
377 # if !defined(NDEBUG)
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.
384 OutputDebugString(pmsg
);
388 (void)DeregisterEventSource(hEventLog
);
391 MessageBox(NULL
, buf
, _T("OpenSSL: FATAL"), MB_OK
| MB_ICONERROR
);
395 MessageBox(NULL
, buf
, _T("OpenSSL: FATAL"), MB_OK
| MB_ICONERROR
);
399 void OPENSSL_showfatal(const char *fmta
, ...)
401 #ifndef OPENSSL_NO_STDIO
405 vfprintf(stderr
, fmta
, ap
);
410 int OPENSSL_isservice(void)
416 void OPENSSL_die(const char *message
, const char *file
, int line
)
418 OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n",
419 file
, line
, message
);
424 * Win32 abort() customarily shows a dialog, but we just did that...
426 # if !defined(_WIN32_WCE)
433 #if !defined(OPENSSL_CPUID_OBJ)
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.
440 * There are also assembler versions of this function.
442 # undef CRYPTO_memcmp
443 int CRYPTO_memcmp(const void * in_a
, const void * in_b
, size_t len
)
446 const volatile unsigned char *a
= in_a
;
447 const volatile unsigned char *b
= in_b
;
450 for (i
= 0; i
< len
; i
++)
457 * For systems that don't provide an instruction counter register or equivalent.
459 uint32_t OPENSSL_rdtsc(void)
464 size_t OPENSSL_instrument_bus(unsigned int *out
, size_t cnt
)
469 size_t OPENSSL_instrument_bus2(unsigned int *out
, size_t cnt
, size_t max
)
475 #if defined(__TANDEM) && defined(OPENSSL_VPROC)
477 * Define a VPROC function for HP NonStop build crypto library.
478 * This is used by platform version identification tools.
479 * Do not inline this procedure or make it static.
481 # define OPENSSL_VPROC_STRING_(x) x##_CRYPTO
482 # define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
483 # define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
484 void OPENSSL_VPROC_FUNC(void) {}
485 #endif /* __TANDEM */