Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
freebl: Make it possible to compile without SSE2
Since this commit:
https://hg.mozilla.org/projects/nss/rev/cd068f7ce6ae11120f8e4427aa2e8ac35a69e764
NSS build always enable the GCC options -mpclmul and -maes.

Although these hardware features can be turned off with
envvars (NSS_DISABLE_PCLMUL, NSS_DISABLE_HW_AES, and NSS_DISABLE_AVX),
these compiler options also require SSE2, which is not yet mandated in
Fedora 27 (i686).

This patch exposes those envvars as a build time option to make it
possible to compile NSS without SSE2.

Reported and analyzed by Tomasz Torcz, Eugene Kanter, and Davide
Repetto in:
https://bugzilla.redhat.com/show_bug.cgi?id=1482798
https://bugzilla.redhat.com/show_bug.cgi?id=1485656
  • Loading branch information
ueno committed Sep 15, 2017
1 parent 9626433 commit 385ae89
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
14 changes: 13 additions & 1 deletion lib/freebl/Makefile
Expand Up @@ -110,7 +110,19 @@ endif
# NSS_X86_OR_X64 means the target is either x86 or x64
ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
DEFINES += -DNSS_X86_OR_X64
CFLAGS += -mpclmul -maes
ifdef NSS_DISABLE_PCLMUL
DEFINES += -DNSS_DISABLE_PCLMUL
else
CFLAGS += -mpclmul
endif
ifdef NSS_DISABLE_HW_AES
DEFINES += -DNSS_DISABLE_HW_AES
else
CFLAGS += -maes
endif
ifdef NSS_DISABLE_AVX
DEFINES += -DNSS_DISABLE_AVX
endif
ifneq (,$(USE_64)$(USE_X32))
DEFINES += -DNSS_X64
else
Expand Down
21 changes: 20 additions & 1 deletion lib/freebl/blinit.c
Expand Up @@ -25,6 +25,8 @@ static PRBool clmul_support_ = PR_FALSE;
static PRBool avx_support_ = PR_FALSE;

#ifdef NSS_X86_OR_X64

#ifndef NSS_DISABLE_AVX
/*
* Adapted from the example code in "How to detect New Instruction support in
* the 4th generation Intel Core processor family" by Max Locktyukhin.
Expand Down Expand Up @@ -56,6 +58,7 @@ check_xcr0_ymm()
/* Check if xmm and ymm state are enabled in XCR0. */
return (xcr0 & 6) == 6;
}
#endif

#define ECX_AESNI (1 << 25)
#define ECX_CLMUL (1 << 1)
Expand All @@ -67,17 +70,33 @@ check_xcr0_ymm()
void
CheckX86CPUSupport()
{
unsigned long eax, ebx, ecx, edx;
#ifndef NSS_DISABLE_HW_AES
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
#endif
#ifndef NSS_DISABLE_PCLMUL
char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL");
#endif
#ifndef NSS_DISABLE_AVX
char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX");
#endif
#if !defined(NSS_DISABLE_HW_AES) || \
!defined(NSS_DISABLE_PCLMUL) || \
!defined(NSS_DISABLE_AVX)
unsigned long eax, ebx, ecx, edx;
freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
#endif
#ifndef NSS_DISABLE_HW_AES
aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL);
#endif
#ifndef NSS_DISABLE_PCLMUL
clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL);
#endif
#ifndef NSS_DISABLE_AVX
/* 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
}
#endif /* NSS_X86_OR_X64 */

Expand Down
20 changes: 13 additions & 7 deletions lib/freebl/gcm.c
Expand Up @@ -18,8 +18,14 @@
#include <limits.h>

#ifdef NSS_X86_OR_X64
/* The x86{,_64} hardware implementation relies on CLMUL */
#ifdef NSS_DISABLE_PCLMUL
#undef DISABLE_HW_GCM
#define DISABLE_HW_GCM 1
#else
#include <wmmintrin.h> /* clmul */
#endif
#endif

/* Forward declarations */
SECStatus gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
Expand Down Expand Up @@ -53,7 +59,7 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
ghash->h_low = get64(H + 8);
ghash->h_high = get64(H);
if (clmul_support() && !sw) {
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_GCM)
ghash->ghash_mul = gcm_HashMult_hw;
ghash->x = _mm_setzero_si128();
/* MSVC requires __m64 to load epi64. */
Expand All @@ -63,7 +69,7 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && !DISABLE_HW_GCM */
} else {
/* We fall back to the software implementation if we can't use / don't
* want to use pclmul. */
Expand Down Expand Up @@ -287,7 +293,7 @@ SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && !defined(NSS_DISABLE_PCLMUL)
size_t i;
pre_align __m128i z_high post_align;
pre_align __m128i z_low post_align;
Expand Down Expand Up @@ -368,13 +374,13 @@ static SECStatus
gcm_zeroX(gcmHashContext *ghash)
{
if (ghash->hw) {
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && defined(__SSE2__)
ghash->x = _mm_setzero_si128();
return SECSuccess;
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && defined(__SSE2__) */
}

ghash->x_high = ghash->x_low = 0;
Expand Down Expand Up @@ -503,15 +509,15 @@ gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
}

if (ghash->hw) {
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_GCM)
uint64_t tmp_out[2];
_mm_storeu_si128((__m128i *)tmp_out, ghash->x);
WRITE64(tmp_out[0], T + 8);
WRITE64(tmp_out[1], T);
#else
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && !DISABLE_HW_GCM */
} else {
WRITE64(ghash->x_low, T + 8);
WRITE64(ghash->x_high, T);
Expand Down
26 changes: 16 additions & 10 deletions lib/freebl/rijndael.c
Expand Up @@ -20,6 +20,12 @@
#include "gcm.h"
#include "mpi.h"

/* The x86{,_64} hardware implementation relies on AES-NI */
#ifdef NSS_DISABLE_HW_AES
#undef DISABLE_HW_AES
#define DISABLE_HW_AES 1
#endif

#ifdef USE_HW_AES
#include "intel-aes.h"
#endif
Expand Down Expand Up @@ -309,7 +315,7 @@ rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int N
}
}

#if defined(NSS_X86_OR_X64)
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
#define EXPAND_KEY128(k, rcon, res) \
tmp_key = _mm_aeskeygenassist_si128(k, rcon); \
tmp_key = _mm_shuffle_epi32(tmp_key, 0xFF); \
Expand Down Expand Up @@ -418,15 +424,15 @@ native_key_expansion256(AESContext *cx, const unsigned char *key)
keySchedule[13], 0xFF);
}

#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && !DISABLE_HW_AES */

/*
* AES key expansion using aes-ni instructions.
*/
static void
native_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
{
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
switch (Nk) {
case 4:
native_key_expansion128(cx, key);
Expand All @@ -443,15 +449,15 @@ native_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk)
}
#else
PORT_Assert(0);
#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && DISABLE_HW_AES */
}

static void
native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input)
{
#ifdef NSS_X86_OR_X64
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
m = _mm_xor_si128(m, cx->keySchedule[0]);
Expand All @@ -462,7 +468,7 @@ native_encryptBlock(AESContext *cx,
_mm_storeu_si128((__m128i *)output, m);
#else
PORT_Assert(0);
#endif /* NSS_X86_OR_X64 */
#endif /* NSS_X86_OR_X64 && DISABLE_HW_AES */
}

/* rijndael_key_expansion
Expand Down Expand Up @@ -637,7 +643,7 @@ rijndael_encryptBlock128(AESContext *cx,
PRUint32 *roundkeyw;
rijndael_state state;
PRUint32 C0, C1, C2, C3;
#if defined(NSS_X86_OR_X64)
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
#define pIn input
#define pOut output
#else
Expand Down Expand Up @@ -713,7 +719,7 @@ rijndael_encryptBlock128(AESContext *cx,
*((PRUint32 *)(pOut + 4)) = C1;
*((PRUint32 *)(pOut + 8)) = C2;
*((PRUint32 *)(pOut + 12)) = C3;
#if defined(NSS_X86_OR_X64)
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
#undef pIn
#undef pOut
#else
Expand All @@ -732,7 +738,7 @@ rijndael_decryptBlock128(AESContext *cx,
PRUint32 *roundkeyw;
rijndael_state state;
PRUint32 C0, C1, C2, C3;
#if defined(NSS_X86_OR_X64)
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
#define pIn input
#define pOut output
#else
Expand Down Expand Up @@ -804,7 +810,7 @@ rijndael_decryptBlock128(AESContext *cx,
*((PRUint32 *)(pOut + 8)) ^= *roundkeyw--;
*((PRUint32 *)(pOut + 4)) ^= *roundkeyw--;
*((PRUint32 *)pOut) ^= *roundkeyw--;
#if defined(NSS_X86_OR_X64)
#if defined(NSS_X86_OR_X64) && !defined(DISABLE_HW_AES)
#undef pIn
#undef pOut
#else
Expand Down

0 comments on commit 385ae89

Please sign in to comment.