diff options
Diffstat (limited to 'security/nss/lib/freebl/blinit.c')
-rw-r--r-- | security/nss/lib/freebl/blinit.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/blinit.c b/security/nss/lib/freebl/blinit.c new file mode 100644 index 000000000..d7f2ec53a --- /dev/null +++ b/security/nss/lib/freebl/blinit.c @@ -0,0 +1,119 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef FREEBL_NO_DEPEND +#include "stubs.h" +#endif + +#include "blapii.h" +#include "mpi.h" +#include "secerr.h" +#include "prtypes.h" +#include "prinit.h" +#include "prenv.h" + +#if defined(_MSC_VER) && !defined(_M_IX86) +#include <intrin.h> /* for _xgetbv() */ +#endif + +static PRCallOnceType coFreeblInit; + +/* State variables. */ +static PRBool aesni_support_ = PR_FALSE; +static PRBool clmul_support_ = PR_FALSE; +static PRBool avx_support_ = PR_FALSE; + +#ifdef NSS_X86_OR_X64 +/* + * Adapted from the example code in "How to detect New Instruction support in + * the 4th generation Intel Core processor family" by Max Locktyukhin. + * + * XGETBV: + * Reads an extended control register (XCR) specified by ECX into EDX:EAX. + */ +static PRBool +check_xcr0_ymm() +{ + PRUint32 xcr0; +#if defined(_MSC_VER) +#if defined(_M_IX86) + __asm { + mov ecx, 0 + xgetbv + mov xcr0, eax + } +#else + xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */ +#endif /* _M_IX86 */ +#else /* _MSC_VER */ + /* Old OSX compilers don't support xgetbv. Use byte form. */ + __asm__(".byte 0x0F, 0x01, 0xd0" + : "=a"(xcr0) + : "c"(0) + : "%edx"); +#endif /* _MSC_VER */ + /* Check if xmm and ymm state are enabled in XCR0. */ + return (xcr0 & 6) == 6; +} + +#define ECX_AESNI (1 << 25) +#define ECX_CLMUL (1 << 1) +#define ECX_XSAVE (1 << 26) +#define ECX_OSXSAVE (1 << 27) +#define ECX_AVX (1 << 28) +#define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX) + +void +CheckX86CPUSupport() +{ + unsigned long eax, ebx, ecx, edx; + char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); + char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL"); + char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX"); + freebl_cpuid(1, &eax, &ebx, &ecx, &edx); + aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL); + clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL); + /* For AVX we check AVX, OSXSAVE, and XSAVE + * as well as XMM and YMM state. */ + avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() && + disable_avx == NULL; +} +#endif /* NSS_X86_OR_X64 */ + +PRBool +aesni_support() +{ + return aesni_support_; +} +PRBool +clmul_support() +{ + return clmul_support_; +} +PRBool +avx_support() +{ + return avx_support_; +} + +static PRStatus +FreeblInit(void) +{ +#ifdef NSS_X86_OR_X64 + CheckX86CPUSupport(); +#endif + return PR_SUCCESS; +} + +SECStatus +BL_Init() +{ + if (PR_CallOnce(&coFreeblInit, FreeblInit) != PR_SUCCESS) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + RSA_Init(); + + return SECSuccess; +} |