Update NSS to 3.48 while keeping vc2013 hackfix and no-sslkeylogfile intact.

This commit is contained in:
Roy Tam 2020-01-03 13:36:26 +08:00
commit 171849c8e5
351 changed files with 115185 additions and 57946 deletions

View file

@ -119,6 +119,26 @@ else
DEFINES += -DNSS_X86
endif
endif
ifeq ($(CPU_ARCH),aarch64)
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c gcm-aarch64.c
endif
ifeq ($(CPU_ARCH),arm)
ifdef CC_IS_CLANG
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c
else ifeq (1,$(CC_IS_GCC))
# Old compiler doesn't support ARM AES.
ifneq (,$(filter 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c
endif
endif
endif
ifeq ($(OS_TARGET),OSF1)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
@ -243,6 +263,7 @@ ifeq ($(CPU_ARCH),arm)
MPI_SRCS += mpi_arm.c
endif
ifeq ($(CPU_ARCH),ppc)
EXTRA_SRCS += gcm-ppc.c
ifdef USE_64
DEFINES += -DNSS_NO_INIT_SUPPORT
endif # USE_64
@ -493,6 +514,9 @@ endif # Solaris for non-sparc family CPUs
endif # target == SunO
ifdef USE_64
# no __int128 at least up to lcc 1.23 (pretending to be gcc5)
# NB: CC_NAME is not defined here
ifneq ($(shell $(CC) -? 2>&1 >/dev/null </dev/null | sed -e 's/:.*//;1q'),lcc)
ifdef CC_IS_CLANG
HAVE_INT128_SUPPORT = 1
DEFINES += -DHAVE_INT128_SUPPORT
@ -506,7 +530,8 @@ ifdef USE_64
DEFINES += -DHAVE_INT128_SUPPORT
endif
endif
endif
endif # lcc
endif # USE_64
ifndef HAVE_INT128_SUPPORT
DEFINES += -DKRML_NOUINT128
@ -753,3 +778,15 @@ ifdef INTEL_GCM_CLANG_CL
#
$(OBJDIR)/$(PROG_PREFIX)intel-gcm-wrap$(OBJ_SUFFIX): CFLAGS += -mssse3
endif
ifeq ($(CPU_ARCH),arm)
$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8
endif
ifeq ($(CPU_ARCH),aarch64)
$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
$(OBJDIR)/$(PROG_PREFIX)gcm-aarch64$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
endif
ifeq ($(CPU_ARCH),ppc)
$(OBJDIR)/$(PROG_PREFIX)gcm-ppc$(OBJ_SUFFIX): CFLAGS += -mcrypto -maltivec
endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,103 @@
/* 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/. */
SECStatus arm_aes_encrypt_ecb_128(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_ecb_128(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_encrypt_cbc_128(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_cbc_128(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_encrypt_ecb_192(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_ecb_192(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_encrypt_cbc_192(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_cbc_192(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_encrypt_ecb_256(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_ecb_256(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_encrypt_cbc_256(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
SECStatus arm_aes_decrypt_cbc_256(AESContext *cx, unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen,
unsigned int blocksize);
#define native_aes_ecb_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? arm_aes_encrypt_ecb_128 \
: (keysize) == 24 ? arm_aes_encrypt_ecb_192 \
: arm_aes_encrypt_ecb_256) \
: ((keysize) == 16 ? arm_aes_decrypt_ecb_128 \
: (keysize) == 24 ? arm_aes_decrypt_ecb_192 \
: arm_aes_decrypt_ecb_256))
#define native_aes_cbc_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? arm_aes_encrypt_cbc_128 \
: (keysize) == 24 ? arm_aes_encrypt_cbc_192 \
: arm_aes_encrypt_cbc_256) \
: ((keysize) == 16 ? arm_aes_decrypt_cbc_128 \
: (keysize) == 24 ? arm_aes_decrypt_cbc_192 \
: arm_aes_decrypt_cbc_256))
#define native_aes_init(encrypt, keysize) \
do { \
if (encrypt) { \
rijndael_key_expansion(cx, key, Nk); \
} else { \
rijndael_invkey_expansion(cx, key, Nk); \
} \
} while (0)

View file

@ -21,7 +21,7 @@
static void
native_key_expansion128(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
__m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
@ -61,7 +61,7 @@ native_key_expansion128(AESContext *cx, const unsigned char *key)
static void
native_key_expansion192(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
__m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
pre_align __m128i tmp3 post_align;
@ -96,7 +96,7 @@ native_key_expansion192(AESContext *cx, const unsigned char *key)
static void
native_key_expansion256(AESContext *cx, const unsigned char *key)
{
__m128i *keySchedule = cx->keySchedule;
__m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
@ -148,10 +148,10 @@ rijndael_native_encryptBlock(AESContext *cx,
{
int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
m = _mm_xor_si128(m, cx->keySchedule[0]);
m = _mm_xor_si128(m, cx->k.keySchedule[0]);
for (i = 1; i < cx->Nr; ++i) {
m = _mm_aesenc_si128(m, cx->keySchedule[i]);
m = _mm_aesenc_si128(m, cx->k.keySchedule[i]);
}
m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
m = _mm_aesenclast_si128(m, cx->k.keySchedule[cx->Nr]);
_mm_storeu_si128((__m128i *)output, m);
}

View file

@ -225,7 +225,8 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
#define A B[0]
/* Check args */
if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
if (inputLen < 2 * AES_KEY_WRAP_BLOCK_SIZE ||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return s;
}

View file

@ -0,0 +1,23 @@
/*
* altivec-types.h - shorter vector typedefs
*
* 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/. */
#ifndef _ALTIVEC_TYPES_H_
#define _ALTIVEC_TYPES_H_ 1
#include <altivec.h>
typedef __vector unsigned char vec_u8;
typedef __vector signed char vec_s8;
typedef __vector unsigned short vec_u16;
typedef __vector signed short vec_s16;
typedef __vector unsigned int vec_u32;
typedef __vector signed int vec_s32;
typedef __vector unsigned long long vec_u64;
typedef __vector signed long long vec_s64;
typedef __vector float vec_f;
#endif

View file

@ -10,6 +10,7 @@
#include "blapit.h"
#include "hasht.h"
#include "cmac.h"
#include "alghmac.h"
SEC_BEGIN_PROTOS

View file

@ -86,5 +86,6 @@ PRBool arm_aes_support();
PRBool arm_pmull_support();
PRBool arm_sha1_support();
PRBool arm_sha2_support();
PRBool ppc_crypto_support();
#endif /* _BLAPII_H_ */

View file

@ -29,6 +29,7 @@ static PRBool arm_aes_support_ = PR_FALSE;
static PRBool arm_sha1_support_ = PR_FALSE;
static PRBool arm_sha2_support_ = PR_FALSE;
static PRBool arm_pmull_support_ = PR_FALSE;
static PRBool ppc_crypto_support_ = PR_FALSE;
#ifdef NSS_X86_OR_X64
/*
@ -137,10 +138,11 @@ CheckARMSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
char *disable_pmull = PR_GetEnvSecure("NSS_DISABLE_PMULL");
if (getauxval) {
long hwcaps = getauxval(AT_HWCAP);
arm_aes_support_ = hwcaps & HWCAP_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP_PMULL;
arm_pmull_support_ = hwcaps & HWCAP_PMULL && disable_pmull == NULL;
arm_sha1_support_ = hwcaps & HWCAP_SHA1;
arm_sha2_support_ = hwcaps & HWCAP_SHA2;
}
@ -204,6 +206,46 @@ GetNeonSupport()
return PR_FALSE;
}
#ifdef __linux__
static long
ReadCPUInfoForHWCAP2()
{
FILE *cpuinfo;
char buf[512];
char *p;
long hwcap2 = 0;
cpuinfo = fopen("/proc/cpuinfo", "r");
if (!cpuinfo) {
return 0;
}
while (fgets(buf, 511, cpuinfo)) {
if (!memcmp(buf, "Features", 8)) {
p = strstr(buf, " aes");
if (p && (p[4] == ' ' || p[4] == '\n')) {
hwcap2 |= HWCAP2_AES;
}
p = strstr(buf, " sha1");
if (p && (p[5] == ' ' || p[5] == '\n')) {
hwcap2 |= HWCAP2_SHA1;
}
p = strstr(buf, " sha2");
if (p && (p[5] == ' ' || p[5] == '\n')) {
hwcap2 |= HWCAP2_SHA2;
}
p = strstr(buf, " pmull");
if (p && (p[6] == ' ' || p[6] == '\n')) {
hwcap2 |= HWCAP2_PMULL;
}
break;
}
}
fclose(cpuinfo);
return hwcap2;
}
#endif /* __linux__ */
void
CheckARMSupport()
{
@ -216,6 +258,13 @@ CheckARMSupport()
// AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
// returns 0.
long hwcaps = getauxval(AT_HWCAP2);
#ifdef __linux__
if (!hwcaps) {
// Some ARMv8 devices may not implement AT_HWCAP2. So we also
// read /proc/cpuinfo if AT_HWCAP2 is 0.
hwcaps = ReadCPUInfoForHWCAP2();
}
#endif
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
@ -300,6 +349,32 @@ arm_sha2_support()
{
return arm_sha2_support_;
}
PRBool
ppc_crypto_support()
{
return ppc_crypto_support_;
}
#if defined(__powerpc__)
#include <sys/auxv.h>
// Defines from cputable.h in Linux kernel - PPC, letting us build on older kernels
#ifndef PPC_FEATURE2_VEC_CRYPTO
#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
#endif
static void
CheckPPCSupport()
{
char *disable_hw_crypto = PR_GetEnvSecure("NSS_DISABLE_PPC_GHASH");
long hwcaps = getauxval(AT_HWCAP2);
ppc_crypto_support_ = hwcaps & PPC_FEATURE2_VEC_CRYPTO && disable_hw_crypto == NULL;
}
#endif /* __powerpc__ */
static PRStatus
FreeblInit(void)
@ -308,6 +383,8 @@ FreeblInit(void)
CheckX86CPUSupport();
#elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport();
#elif (defined(__powerpc__))
CheckPPCSupport();
#endif
return PR_SUCCESS;
}

View file

@ -210,8 +210,7 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
*outputLen = inputLen + ctx->tagLen;
if (maxOutputLen < *outputLen) {
if (maxOutputLen < inputLen + ctx->tagLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@ -227,6 +226,7 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
Poly1305Do(tag, ad, adLen, output, inputLen, block);
PORT_Memcpy(output + inputLen, tag, ctx->tagLen);
*outputLen = inputLen + ctx->tagLen;
return SECSuccess;
#endif
}
@ -254,11 +254,15 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
return SECFailure;
}
ciphertextLen = inputLen - ctx->tagLen;
*outputLen = ciphertextLen;
if (maxOutputLen < *outputLen) {
if (maxOutputLen < ciphertextLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (inputLen >= (1ULL << (6 + 32)) + ctx->tagLen) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
PORT_Memset(block, 0, sizeof(block));
// Generate a block of keystream. The first 32 bytes will be the poly1305
@ -274,6 +278,7 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
ChaCha20Xor(output, (uint8_t *)input, ciphertextLen, (uint8_t *)ctx->key,
(uint8_t *)nonce, 1);
*outputLen = ciphertextLen;
return SECSuccess;
#endif
}

View file

@ -0,0 +1,322 @@
/* 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 "rijndael.h"
#include "blapi.h"
#include "cmac.h"
#include "secerr.h"
#include "nspr.h"
struct CMACContextStr {
/* Information about the block cipher to use internally. The cipher should
* be placed in ECB mode so that we can use it to directly encrypt blocks.
*
*
* To add a new cipher, add an entry to CMACCipher, update CMAC_Init,
* cmac_Encrypt, and CMAC_Destroy methods to handle the new cipher, and
* add a new Context pointer to the cipher union with the correct type. */
CMACCipher cipherType;
union {
AESContext aes;
} cipher;
int blockSize;
/* Internal keys which are conditionally used by the algorithm. Derived
* from encrypting the NULL block. We leave the storing of (and the
* cleanup of) the CMAC key to the underlying block cipher. */
unsigned char k1[MAX_BLOCK_SIZE];
unsigned char k2[MAX_BLOCK_SIZE];
/* When Update is called with data which isn't a multiple of the block
* size, we need a place to put it. HMAC handles this by passing it to
* the underlying hash function right away; we can't do that as the
* contract on the cipher object is different. */
unsigned int partialIndex;
unsigned char partialBlock[MAX_BLOCK_SIZE];
/* Last encrypted block. This gets xor-ed with partialBlock prior to
* encrypting it. NIST defines this to be the empty string to begin. */
unsigned char lastBlock[MAX_BLOCK_SIZE];
};
static void
cmac_ShiftLeftOne(unsigned char *out, const unsigned char *in, int length)
{
int i = 0;
for (; i < length - 1; i++) {
out[i] = in[i] << 1;
out[i] |= in[i + 1] >> 7;
}
out[i] = in[i] << 1;
}
static SECStatus
cmac_Encrypt(CMACContext *ctx, unsigned char *output,
const unsigned char *input,
unsigned int inputLen)
{
if (ctx->cipherType == CMAC_AES) {
unsigned int tmpOutputLen;
SECStatus rv = AES_Encrypt(&ctx->cipher.aes, output, &tmpOutputLen,
ctx->blockSize, input, inputLen);
/* Assumption: AES_Encrypt (when in ECB mode) always returns an
* output of length equal to blockSize (what was pass as the value
* of the maxOutputLen parameter). */
PORT_Assert(tmpOutputLen == ctx->blockSize);
return rv;
}
return SECFailure;
}
/* NIST SP.800-38B, 6.1 Subkey Generation */
static SECStatus
cmac_GenerateSubkeys(CMACContext *ctx)
{
unsigned char null_block[MAX_BLOCK_SIZE] = { 0 };
unsigned char L[MAX_BLOCK_SIZE];
unsigned char v;
unsigned char i;
/* Step 1: L = AES(key, null_block) */
if (cmac_Encrypt(ctx, L, null_block, ctx->blockSize) != SECSuccess) {
return SECFailure;
}
/* In the following, some effort has been made to be constant time. Rather
* than conditioning on the value of the MSB (of L or K1), we use the loop
* to build a mask for the conditional constant. */
/* Step 2: If MSB(L) = 0, K1 = L << 1. Else, K1 = (L << 1) ^ R_b. */
cmac_ShiftLeftOne(ctx->k1, L, ctx->blockSize);
v = L[0] >> 7;
for (i = 1; i <= 7; i <<= 1) {
v |= (v << i);
}
ctx->k1[ctx->blockSize - 1] ^= (0x87 & v);
/* Step 3: If MSB(K1) = 0, K2 = K1 << 1. Else, K2 = (K1 <, 1) ^ R_b. */
cmac_ShiftLeftOne(ctx->k2, ctx->k1, ctx->blockSize);
v = ctx->k1[0] >> 7;
for (i = 1; i <= 7; i <<= 1) {
v |= (v << i);
}
ctx->k2[ctx->blockSize - 1] ^= (0x87 & v);
/* Any intermediate value in the computation of the subkey shall be
* secret. */
PORT_Memset(null_block, 0, MAX_BLOCK_SIZE);
PORT_Memset(L, 0, MAX_BLOCK_SIZE);
/* Step 4: Return the values. */
return SECSuccess;
}
/* NIST SP.800-38B, 6.2 MAC Generation step 6 */
static SECStatus
cmac_UpdateState(CMACContext *ctx)
{
if (ctx == NULL || ctx->partialIndex != ctx->blockSize) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Step 6: C_i = CIPHER(key, C_{i-1} ^ M_i) for 1 <= i <= n, and
* C_0 is defined as the empty string. */
for (unsigned int index = 0; index < ctx->blockSize; index++) {
ctx->partialBlock[index] ^= ctx->lastBlock[index];
}
return cmac_Encrypt(ctx, ctx->lastBlock, ctx->partialBlock, ctx->blockSize);
}
SECStatus
CMAC_Init(CMACContext *ctx, CMACCipher type,
const unsigned char *key, unsigned int key_len)
{
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
/* We only currently support AES-CMAC. */
if (type != CMAC_AES) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
PORT_Memset(ctx, 0, sizeof(*ctx));
ctx->blockSize = AES_BLOCK_SIZE;
ctx->cipherType = CMAC_AES;
if (AES_InitContext(&ctx->cipher.aes, key, key_len, NULL, NSS_AES, 1,
ctx->blockSize) != SECSuccess) {
return SECFailure;
}
return CMAC_Begin(ctx);
}
CMACContext *
CMAC_Create(CMACCipher type, const unsigned char *key,
unsigned int key_len)
{
CMACContext *result = PORT_New(CMACContext);
if (CMAC_Init(result, type, key, key_len) != SECSuccess) {
CMAC_Destroy(result, PR_TRUE);
return NULL;
}
return result;
}
SECStatus
CMAC_Begin(CMACContext *ctx)
{
if (ctx == NULL) {
return SECFailure;
}
/* Ensure that our blockSize is less than the maximum. When this fails,
* a cipher with a larger block size was added and MAX_BLOCK_SIZE needs
* to be updated accordingly. */
PORT_Assert(ctx->blockSize <= MAX_BLOCK_SIZE);
if (cmac_GenerateSubkeys(ctx) != SECSuccess) {
return SECFailure;
}
/* Set the index to write partial blocks at to zero. This saves us from
* having to clear ctx->partialBlock. */
ctx->partialIndex = 0;
/* Step 5: Let C_0 = 0^b. */
PORT_Memset(ctx->lastBlock, 0, ctx->blockSize);
return SECSuccess;
}
/* NIST SP.800-38B, 6.2 MAC Generation */
SECStatus
CMAC_Update(CMACContext *ctx, const unsigned char *data,
unsigned int data_len)
{
int data_index = 0;
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (data == NULL || data_len == 0) {
return SECSuccess;
}
/* Copy as many bytes from data into ctx->partialBlock as we can, up to
* the maximum of the remaining data and the remaining space in
* ctx->partialBlock.
*
* Note that we swap the order (encrypt *then* copy) because the last
* block is different from the rest. If we end on an even multiple of
* the block size, we have to be able to XOR it with K1. But we won't know
* that it is the last until CMAC_Finish is called (and by then, CMAC_Update
* has already returned). */
while (data_index < data_len) {
if (ctx->partialIndex == ctx->blockSize) {
if (cmac_UpdateState(ctx) != SECSuccess) {
return SECFailure;
}
ctx->partialIndex = 0;
}
unsigned int copy_len = data_len - data_index;
if (copy_len > (ctx->blockSize - ctx->partialIndex)) {
copy_len = ctx->blockSize - ctx->partialIndex;
}
PORT_Memcpy(ctx->partialBlock + ctx->partialIndex, data + data_index, copy_len);
data_index += copy_len;
ctx->partialIndex += copy_len;
}
return SECSuccess;
}
/* NIST SP.800-38B, 6.2 MAC Generation */
SECStatus
CMAC_Finish(CMACContext *ctx, unsigned char *result,
unsigned int *result_len,
unsigned int max_result_len)
{
if (ctx == NULL || result == NULL || max_result_len == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (max_result_len > ctx->blockSize) {
/* This is a weird situation. The PKCS #11 soft tokencode passes
* sizeof(result) here, which is hard-coded as SFTK_MAX_MAC_LENGTH.
* This later gets truncated to min(SFTK_MAX_MAC_LENGTH, requested). */
max_result_len = ctx->blockSize;
}
/* Step 4: If M_n* is a complete block, M_n = K1 ^ M_n*. Else,
* M_n = K2 ^ (M_n* || 10^j). */
if (ctx->partialIndex == ctx->blockSize) {
/* XOR in K1. */
for (unsigned int index = 0; index < ctx->blockSize; index++) {
ctx->partialBlock[index] ^= ctx->k1[index];
}
} else {
/* Use 10* padding on the partial block. */
ctx->partialBlock[ctx->partialIndex++] = 0x80;
PORT_Memset(ctx->partialBlock + ctx->partialIndex, 0,
ctx->blockSize - ctx->partialIndex);
ctx->partialIndex = ctx->blockSize;
/* XOR in K2. */
for (unsigned int index = 0; index < ctx->blockSize; index++) {
ctx->partialBlock[index] ^= ctx->k2[index];
}
}
/* Encrypt the block. */
if (cmac_UpdateState(ctx) != SECSuccess) {
return SECFailure;
}
/* Step 7 & 8: T = MSB_tlen(C_n); return T. */
PORT_Memcpy(result, ctx->lastBlock, max_result_len);
if (result_len != NULL) {
*result_len = max_result_len;
}
return SECSuccess;
}
void
CMAC_Destroy(CMACContext *ctx, PRBool free_it)
{
if (ctx == NULL) {
return;
}
if (ctx->cipherType == CMAC_AES) {
AES_DestroyContext(&ctx->cipher.aes, PR_FALSE);
}
/* Destroy everything in the context. This includes sensitive data in
* K1, K2, and lastBlock. */
PORT_Memset(ctx, 0, sizeof(*ctx));
if (free_it == PR_TRUE) {
PORT_Free(ctx);
}
}

View file

@ -0,0 +1,47 @@
/* 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/. */
#ifndef _CMAC_H_
#define _CMAC_H_
typedef struct CMACContextStr CMACContext;
SEC_BEGIN_PROTOS
/* Enum for identifying the underlying block cipher we're using internally. */
typedef enum {
CMAC_AES = 0
} CMACCipher;
/* Initialize an existing CMACContext struct. */
SECStatus CMAC_Init(CMACContext *ctx, CMACCipher type,
const unsigned char *key, unsigned int key_len);
/* Allocate and initialize a new CMAC context with the specified cipher and
* key. */
CMACContext *CMAC_Create(CMACCipher type, const unsigned char *key,
unsigned int key_len);
/* Called automatically by CMAC_*{Create,Init}(...). Only useful for restarting
* an already-started CMAC instance. */
SECStatus CMAC_Begin(CMACContext *ctx);
/* Add the specified bytes into the CMAC state. */
SECStatus CMAC_Update(CMACContext *ctx, const unsigned char *data,
unsigned int data_len);
/* Finalize the CMAC state and return the result. */
SECStatus CMAC_Finish(CMACContext *ctx, unsigned char *result,
unsigned int *result_len,
unsigned int max_result_len);
/* Note: CMAC_Clone isn't implemented here because AES doesn't expose a
* context-cloning operation. */
/* Destroy a CMAC context, optionally freeing it. */
void CMAC_Destroy(CMACContext *ctx, PRBool free_it);
SEC_END_PROTOS
#endif

View file

@ -90,12 +90,7 @@ EXTRA_SHARED_LIBS += \
endif
endif
ifeq (,$(filter-out DragonFly FreeBSD Linux NetBSD OpenBSD, $(OS_TARGET)))
CFLAGS += -std=gnu99
endif
ifeq ($(OS_ARCH), Darwin)
CFLAGS += -std=gnu99
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
endif

View file

@ -17,6 +17,10 @@
#include "rijndael.h"
#endif
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
#include <arm_neon.h>
#endif
SECStatus
CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
const unsigned char *param)
@ -114,6 +118,15 @@ ctr_xor(unsigned char *target, const unsigned char *x,
const unsigned char *y, unsigned int count)
{
unsigned int i;
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
while (count >= 16) {
vst1q_u8(target, veorq_u8(vld1q_u8(x), vld1q_u8(y)));
target += 16;
x += 16;
y += 16;
count -= 16;
}
#endif
for (i = 0; i < count; i++) {
*target++ = *x++ ^ *y++;
}
@ -128,6 +141,12 @@ CTR_Update(CTRContext *ctr, unsigned char *outbuf,
unsigned int tmp;
SECStatus rv;
// Limit block count to 2^counterBits - 2
if (ctr->counterBits < (sizeof(unsigned int) * 8) &&
inlen > ((1 << ctr->counterBits) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
@ -199,6 +218,12 @@ CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
unsigned int tmp;
SECStatus rv;
// Limit block count to 2^counterBits - 2
if (ctr->counterBits < (sizeof(unsigned int) * 8) &&
inlen > ((1 << ctr->counterBits) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);

View file

@ -30,6 +30,7 @@
#define PRNG_ADDITONAL_DATA_CACHE_SIZE (8 * 1024) /* must be less than \
* PRNG_MAX_ADDITIONAL_BYTES \
*/
#define PRNG_ENTROPY_BLOCK_SIZE SHA256_LENGTH
/* RESEED_COUNT is how many calls to the prng before we need to reseed
* under normal NIST rules, you must return an error. In the NSS case, we
@ -96,6 +97,8 @@ struct RNGContextStr {
PRUint32 additionalAvail;
PRBool isValid; /* false if RNG reaches an invalid state */
PRBool isKatTest; /* true if running NIST PRNG KAT tests */
/* for continuous entropy check */
PRUint8 previousEntropyHash[SHA256_LENGTH];
};
typedef struct RNGContextStr RNGContext;
@ -169,6 +172,82 @@ prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
return SECSuccess;
}
static PRCallOnceType coRNGInitEntropy;
static PRStatus
prng_initEntropy(void)
{
size_t length;
PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
SHA256Context ctx;
/* For FIPS 140-2 4.9.2 continuous random number generator test,
* fetch the initial entropy from the system RNG and keep it for
* later comparison. */
length = RNG_SystemRNG(block, sizeof(block));
if (length == 0) {
return PR_FAILURE; /* error is already set */
}
PORT_Assert(length == sizeof(block));
/* Store the hash of the entropy block rather than the block
* itself for backward secrecy. */
SHA256_Begin(&ctx);
SHA256_Update(&ctx, block, sizeof(block));
SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
sizeof(globalrng->previousEntropyHash));
PORT_Memset(block, 0, sizeof(block));
return PR_SUCCESS;
}
static SECStatus
prng_getEntropy(PRUint8 *buffer, size_t requestLength)
{
size_t total = 0;
PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
PRUint8 hash[SHA256_LENGTH];
SHA256Context ctx;
SECStatus rv = SECSuccess;
if (PR_CallOnce(&coRNGInitEntropy, prng_initEntropy) != PR_SUCCESS) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
/* For FIPS 140-2 4.9.2 continuous random generator test,
* iteratively fetch fixed sized blocks from the system and
* compare consecutive blocks. */
while (total < requestLength) {
size_t length = RNG_SystemRNG(block, sizeof(block));
if (length == 0) {
rv = SECFailure; /* error is already set */
goto out;
}
PORT_Assert(length == sizeof(block));
/* Store the hash of the entropy block rather than the block
* itself for backward secrecy. */
SHA256_Begin(&ctx);
SHA256_Update(&ctx, block, sizeof(block));
SHA256_End(&ctx, hash, NULL, sizeof(hash));
if (PORT_Memcmp(globalrng->previousEntropyHash, hash, sizeof(hash)) == 0) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
goto out;
}
PORT_Memcpy(globalrng->previousEntropyHash, hash, sizeof(hash));
length = PR_MIN(requestLength - total, sizeof(block));
PORT_Memcpy(buffer, block, length);
total += length;
buffer += length;
}
out:
PORT_Memset(block, 0, sizeof block);
return rv;
}
/*
* Update the global random number generator with more seeding
* material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
@ -182,11 +261,15 @@ prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
{
PRUint8 noiseData[(sizeof rng->V_Data) + PRNG_SEEDLEN];
PRUint8 *noise = &noiseData[0];
SECStatus rv;
/* if entropy wasn't supplied, fetch it. (normal operation case) */
if (entropy == NULL) {
entropy_len = (unsigned int)RNG_SystemRNG(
&noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
entropy_len = PRNG_SEEDLEN;
rv = prng_getEntropy(&noiseData[sizeof rng->V_Data], entropy_len);
if (rv != SECSuccess) {
return SECFailure; /* error is already set */
}
} else {
/* NOTE: this code is only available for testing, not to applications */
/* if entropy was too big for the stack variable, get it from malloc */
@ -384,7 +467,6 @@ static PRStatus
rng_init(void)
{
PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */
unsigned int numBytes;
SECStatus rv = SECSuccess;
if (globalrng == NULL) {
@ -403,18 +485,17 @@ rng_init(void)
}
/* Try to get some seed data for the RNG */
numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes);
PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
if (numBytes != 0) {
rv = prng_getEntropy(bytes, sizeof bytes);
if (rv == SECSuccess) {
/* if this is our first call, instantiate, otherwise reseed
* prng_instantiate gets a new clean state, we want to mix
* any previous entropy we may have collected */
if (V(globalrng)[0] == 0) {
rv = prng_instantiate(globalrng, bytes, numBytes);
rv = prng_instantiate(globalrng, bytes, sizeof bytes);
} else {
rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
rv = prng_reseed_test(globalrng, bytes, sizeof bytes, NULL, 0);
}
memset(bytes, 0, numBytes);
memset(bytes, 0, sizeof bytes);
} else {
PZ_DestroyLock(globalrng->lock);
globalrng->lock = NULL;

View file

@ -24,7 +24,7 @@ static const ECMethod kMethods[] = {
static const ECMethod *
ec_get_method_from_name(ECCurveName name)
{
int i;
unsigned long i;
for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
if (kMethods[i].name == name) {
return &kMethods[i];

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,7 @@
},
{
'files': [
'cmac.h',
'alghmac.h',
'blapi.h',
'blake2b.h',

View file

@ -116,6 +116,69 @@
}]
]
},
{
'target_name': 'gcm-aes-aarch64_c_lib',
'type': 'static_library',
'sources': [
'gcm-aarch64.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'cflags': [
'-march=armv8-a+crypto'
],
'cflags_mozilla': [
'-march=armv8-a+crypto'
]
},
{
'target_name': 'gcm-aes-ppc_c_lib',
'type': 'static_library',
'sources': [
'gcm-ppc.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'cflags': [
'-mcrypto',
'-maltivec'
],
'cflags_mozilla': [
'-mcrypto',
'-maltivec'
]
},
{
'target_name': 'armv8_c_lib',
'type': 'static_library',
'sources': [
'aes-armv8.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'target_arch=="arm"', {
'cflags': [
'-march=armv8-a',
'-mfpu=crypto-neon-fp-armv8'
],
'cflags_mozilla': [
'-march=armv8-a',
'-mfpu=crypto-neon-fp-armv8'
],
}, 'target_arch=="arm64" or target_arch=="aarch64"', {
'cflags': [
'-march=armv8-a+crypto'
],
'cflags_mozilla': [
'-march=armv8-a+crypto'
],
}]
]
},
{
'target_name': 'freebl',
'type': 'static_library',
@ -126,9 +189,9 @@
'<(DEPTH)/exports.gyp:nss_exports'
]
},
# For test builds, build a static freebl library so we can statically
# link it into the test build binary. This way we don't have to
# dlopen() the shared lib but can directly call freebl functions.
# Build a static freebl library so we can statically link it into
# the binary. This way we don't have to dlopen() the shared lib
# but can directly call freebl functions.
{
'target_name': 'freebl_static',
'type': 'static_library',
@ -144,6 +207,20 @@
'dependencies': [
'gcm-aes-x86_c_lib',
],
}, 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'dependencies': [
'armv8_c_lib'
],
}],
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
'dependencies': [
'gcm-aes-aarch64_c_lib',
],
}],
[ 'target_arch=="ppc64le"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
],
}],
[ 'OS=="linux"', {
'defines!': [
@ -154,7 +231,7 @@
],
'conditions': [
[ 'target_arch=="x64"', {
# The AES assembler code doesn't work in static test builds.
# The AES assembler code doesn't work in static builds.
# The linker complains about non-relocatable code, and I
# currently don't know how to fix this properly.
'sources!': [
@ -181,8 +258,22 @@
'dependencies': [
'gcm-aes-x86_c_lib',
]
}, 'target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64"', {
'dependencies': [
'armv8_c_lib',
],
}],
[ 'OS!="linux" and OS!="android"', {
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
'dependencies': [
'gcm-aes-aarch64_c_lib',
],
}],
[ 'target_arch=="ppc64" or target_arch=="ppc64le"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
],
}],
[ 'OS!="linux"', {
'conditions': [
[ 'moz_fold_libs==0', {
'dependencies': [
@ -194,7 +285,8 @@
],
}],
],
}, 'target_arch=="x64"', {
}],
[ '(OS=="linux" or OS=="android") and target_arch=="x64"', {
'dependencies': [
'intel-gcm-wrap_c_lib',
],
@ -221,6 +313,43 @@
]
},
},
{
'target_name': 'freebl_64int_3',
'includes': [
'freebl_base.gypi',
],
'type': 'shared_library',
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
],
},
{
'target_name': 'freebl_64fpu_3',
'includes': [
'freebl_base.gypi',
],
'type': 'shared_library',
'sources': [
'mpi/mpi_sparc.c',
'mpi/mpv_sparcv9.s',
'mpi/montmulfv9.s',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
],
'asflags_mozilla': [
'-mcpu=v9', '-Wa,-xarch=v9a'
],
'defines': [
'MP_NO_MP_WORD',
'MP_USE_UINT_DIGIT',
'MP_ASSEMBLY_MULTIPLY',
'MP_USING_MONT_MULF',
'MP_MONT_USE_MP_MUL',
],
},
],
'conditions': [
[ 'OS=="linux"', {
@ -260,15 +389,6 @@
'MP_API_COMPATIBLE'
],
'conditions': [
[ 'OS=="mac"', {
'xcode_settings': {
# I'm not sure since when this is supported.
# But I hope that doesn't matter. We also assume this is x86/x64.
'OTHER_CFLAGS': [
'-std=gnu99',
],
},
}],
[ 'OS=="win" and target_arch=="ia32"', {
'msvs_settings': {
'VCCLCompilerTool': {
@ -323,14 +443,6 @@
'FREEBL_LOWHASH',
'FREEBL_NO_DEPEND',
],
'cflags': [
'-std=gnu99',
],
}],
[ 'OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
'cflags': [
'-std=gnu99',
],
}],
[ 'OS=="linux" or OS=="android"', {
'conditions': [
@ -367,6 +479,11 @@
'ARMHF',
],
}],
[ 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'defines': [
'USE_HW_AES',
],
}],
],
}],
],

View file

@ -5,6 +5,7 @@
'sources': [
'aeskeywrap.c',
'alg2268.c',
'cmac.c',
'alghmac.c',
'arcfive.c',
'arcfour.c',
@ -99,7 +100,7 @@
}],
[ 'OS=="win"', {
'libraries': [
'advapi32.lib',
'-ladvapi32',
],
'conditions': [
[ 'cc_use_gnu_ld!=1 and target_arch=="x64"', {

View file

@ -0,0 +1,96 @@
/* 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 "gcm.h"
#include "secerr.h"
/* old gcc doesn't support some poly64x2_t intrinsic */
#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
(defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
#include <arm_neon.h>
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
uint8x16_t ci = vrbitq_u8(vreinterpretq_u8_u64(ghash->x));
vst1q_u8(outbuf, ci);
return SECSuccess;
}
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
const poly64x2_t p = vdupq_n_p64(0x87);
const uint8x16_t zero = vdupq_n_u8(0);
const uint64x2_t h = ghash->h;
uint64x2_t ci = ghash->x;
unsigned int i;
uint8x16_t z_low, z_high;
uint8x16_t t_low, t_high;
poly64x2_t t1;
uint8x16_t t2;
for (i = 0; i < count; i++, buf += 16) {
ci = vreinterpretq_u64_u8(veorq_u8(vreinterpretq_u8_u64(ci),
vrbitq_u8(vld1q_u8(buf))));
/* Do binary mult ghash->X = Ci * ghash->H. */
z_low = vreinterpretq_u8_p128(
vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u64(ci)),
(poly64_t)vget_low_p64(vreinterpretq_p64_u64(h))));
z_high = vreinterpretq_u8_p128(
vmull_high_p64(vreinterpretq_p64_u64(ci), vreinterpretq_p64_u64(h)));
t1 = vreinterpretq_p64_u8(
vextq_u8(vreinterpretq_u8_u64(h), vreinterpretq_u8_u64(h), 8));
t_low = vreinterpretq_u8_p128(
vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u64(ci)),
(poly64_t)vget_low_p64(t1)));
t_high = vreinterpretq_u8_p128(vmull_high_p64(vreinterpretq_p64_u64(ci), t1));
t2 = veorq_u8(t_high, t_low);
z_low = veorq_u8(z_low, vextq_u8(zero, t2, 8));
z_high = veorq_u8(z_high, vextq_u8(t2, zero, 8));
/* polynomial reduction */
t2 = vreinterpretq_u8_p128(vmull_high_p64(vreinterpretq_p64_u8(z_high), p));
z_high = veorq_u8(z_high, vextq_u8(t2, zero, 8));
z_low = veorq_u8(z_low, vextq_u8(zero, t2, 8));
ci = veorq_u64(vreinterpretq_u64_u8(z_low),
vreinterpretq_u64_p128(
vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u8(z_high)),
(poly64_t)vget_low_p64(p))));
}
ghash->x = ci;
return SECSuccess;
}
SECStatus
gcm_HashInit_hw(gcmHashContext *ghash)
{
/* Workaround of "used uninitialized in this function" error */
uint64x2_t h = vdupq_n_u64(0);
ghash->ghash_mul = gcm_HashMult_hw;
ghash->x = vdupq_n_u64(0);
h = vsetq_lane_u64(__builtin_bswap64(ghash->h_low), h, 1);
h = vsetq_lane_u64(__builtin_bswap64(ghash->h_high), h, 0);
h = vreinterpretq_u64_u8(vrbitq_u8(vreinterpretq_u8_u64(h)));
ghash->h = h;
ghash->hw = PR_TRUE;
return SECSuccess;
}
SECStatus
gcm_HashZeroX_hw(gcmHashContext *ghash)
{
ghash->x = vdupq_n_u64(0);
return SECSuccess;
}
#endif /* defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 6) */

View file

@ -0,0 +1,109 @@
/* 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 "gcm.h"
#include "secerr.h"
#if defined(USE_PPC_CRYPTO)
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
vec_xst_be((vec_u8)ghash->x, 0, outbuf);
return SECSuccess;
}
static vec_u64
vpmsumd(const vec_u64 a, const vec_u64 b)
{
#if defined(__clang__)
/* Clang uses a different name */
return __builtin_altivec_crypto_vpmsumd(a, b);
#elif (__GNUC__ >= 10) || (__GNUC__ == 9 && __GNUC_MINOR__ >= 3) || \
(__GNUC__ == 8 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ == 7 && __GNUC_MINOR__ >= 5)
/* GCC versions not affected by https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91275 */
return __builtin_crypto_vpmsumd(a, b);
#else
/* GCC versions where this builtin is buggy */
vec_u64 vr;
__asm("vpmsumd %0, %1, %2"
: "=v"(vr)
: "v"(a), "v"(b));
return vr;
#endif
}
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
const vec_u8 leftshift = vec_splat_u8(1);
const vec_u64 onebit = (vec_u64){ 1, 0 };
const unsigned long long pd = 0xc2LLU << 56;
vec_u64 ci, v, r0, r1;
vec_u64 hibit;
unsigned i;
ci = ghash->x;
for (i = 0; i < count; i++, buf += 16) {
/* clang needs the following cast away from const; maybe a bug in 7.0.0 */
v = (vec_u64)vec_xl_be(0, (unsigned char *)buf);
ci ^= v;
/* Do binary mult ghash->X = C * ghash->H (Karatsuba). */
r0 = vpmsumd((vec_u64){ ci[0], 0 }, (vec_u64){ ghash->h[0], 0 });
r1 = vpmsumd((vec_u64){ ci[1], 0 }, (vec_u64){ ghash->h[1], 0 });
v = (vec_u64){ ci[0] ^ ci[1], ghash->h[0] ^ ghash->h[1] };
v = vpmsumd((vec_u64){ v[0], 0 }, (vec_u64){ v[1], 0 });
v ^= r0;
v ^= r1;
r0 ^= (vec_u64){ 0, v[0] };
r1 ^= (vec_u64){ v[1], 0 };
/* Shift one (multiply by x) as gcm spec is stupid. */
hibit = (vec_u64)vec_splat((vec_u8)r0, 15);
hibit = (vec_u64)vec_rl((vec_u8)hibit, leftshift);
hibit &= onebit;
r0 = vec_sll(r0, leftshift);
r1 = vec_sll(r1, leftshift);
r1 |= hibit;
/* Reduce */
v = vpmsumd((vec_u64){ r0[0], 0 }, (vec_u64){ pd, 0 });
r0 ^= (vec_u64){ 0, v[0] };
r1 ^= (vec_u64){ v[1], 0 };
v = vpmsumd((vec_u64){ r0[1], 0 }, (vec_u64){ pd, 0 });
r1 ^= v;
ci = r0 ^ r1;
}
ghash->x = ci;
return SECSuccess;
}
SECStatus
gcm_HashInit_hw(gcmHashContext *ghash)
{
ghash->x = (vec_u64)vec_splat_u32(0);
ghash->h = (vec_u64){ ghash->h_low, ghash->h_high };
ghash->ghash_mul = gcm_HashMult_hw;
ghash->hw = PR_TRUE;
return SECSuccess;
}
SECStatus
gcm_HashZeroX_hw(gcmHashContext *ghash)
{
ghash->x = (vec_u64)vec_splat_u32(0);
return SECSuccess;
}
#endif /* defined(USE_PPC_CRYPTO) */

View file

@ -17,6 +17,12 @@
#include <limits.h>
/* old gcc doesn't support some poly64x2_t intrinsic */
#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
(defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
#define USE_ARM_GCM
#endif
/* Forward declarations */
SECStatus gcm_HashInit_hw(gcmHashContext *ghash);
SECStatus gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf);
@ -30,7 +36,7 @@ SECStatus gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
/* Stub definitions for the above *_hw functions, which shouldn't be
* used unless NSS_X86_OR_X64 is defined */
#ifndef NSS_X86_OR_X64
#if !defined(NSS_X86_OR_X64) && !defined(USE_ARM_GCM) && !defined(USE_PPC_CRYPTO)
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
@ -59,7 +65,7 @@ gcm_HashZeroX_hw(gcmHashContext *ghash)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
#endif /* NSS_X86_OR_X64 */
#endif /* !NSS_X86_OR_X64 && !USE_ARM_GCM && !USE_PPC_CRYPTO */
uint64_t
get64(const unsigned char *bytes)
@ -86,7 +92,13 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
ghash->h_low = get64(H + 8);
ghash->h_high = get64(H);
#ifdef USE_ARM_GCM
if (arm_pmull_support() && !sw) {
#elif defined(USE_PPC_CRYPTO)
if (ppc_crypto_support() && !sw) {
#else
if (clmul_support() && !sw) {
#endif
rv = gcm_HashInit_hw(ghash);
} else {
/* We fall back to the software implementation if we can't use / don't
@ -469,6 +481,12 @@ gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
{
SECStatus rv;
// Limit AADLen in accordance with SP800-38D
if (sizeof(AADLen) >= 8 && AADLen > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
ghash->cLen = 0;
PORT_Memset(ghash->counterBuf, 0, GCM_HASH_LEN_LEN * 2);
ghash->bufLen = 0;
@ -525,6 +543,15 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
gcmParams->ulTagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
gcm = PORT_ZNew(GCMContext);
if (gcm == NULL) {
return NULL;

View file

@ -26,6 +26,32 @@
#endif /* NSS_DISABLE_SSE2 */
#endif
#ifdef __aarch64__
#include <arm_neon.h>
#endif
#ifdef __powerpc64__
#include "altivec-types.h"
/* The ghash freebl test tries to use this in C++, and gcc defines conflict. */
#ifdef __cplusplus
#undef pixel
#undef vector
#undef bool
#endif
/*
* PPC CRYPTO requires at least gcc 5 or clang. The LE check is purely
* because it's only been tested on LE. If you're interested in BE,
* please send a patch.
*/
#if (defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 5)) && \
defined(IS_LITTLE_ENDIAN)
#define USE_PPC_CRYPTO
#endif
#endif
SEC_BEGIN_PROTOS
#ifdef HAVE_INT128_SUPPORT
@ -61,6 +87,10 @@ typedef SECStatus (*ghash_t)(gcmHashContext *, const unsigned char *,
pre_align struct gcmHashContextStr {
#ifdef NSS_X86_OR_X64
__m128i x, h;
#elif defined(__aarch64__)
uint64x2_t x, h;
#elif defined(USE_PPC_CRYPTO)
vec_u64 x, h;
#endif
uint64_t x_low, x_high, h_high, h_low;
unsigned char buffer[MAX_BLOCK_SIZE];

View file

@ -100,7 +100,7 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
unsigned int inputLen,
unsigned int blocksize);
#define intel_aes_ecb_worker(encrypt, keysize) \
#define native_aes_ecb_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? intel_aes_encrypt_ecb_128 \
: (keysize) == 24 ? intel_aes_encrypt_ecb_192 \
@ -109,7 +109,7 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
: (keysize) == 24 ? intel_aes_decrypt_ecb_192 \
: intel_aes_decrypt_ecb_256))
#define intel_aes_cbc_worker(encrypt, keysize) \
#define native_aes_cbc_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? intel_aes_encrypt_cbc_128 \
: (keysize) == 24 ? intel_aes_encrypt_cbc_192 \
@ -123,21 +123,21 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
: (nr) == 12 ? intel_aes_encrypt_ctr_192 \
: intel_aes_encrypt_ctr_256)
#define intel_aes_init(encrypt, keysize) \
do { \
if (encrypt) { \
if (keysize == 16) \
intel_aes_encrypt_init_128(key, cx->expandedKey); \
else if (keysize == 24) \
intel_aes_encrypt_init_192(key, cx->expandedKey); \
else \
intel_aes_encrypt_init_256(key, cx->expandedKey); \
} else { \
if (keysize == 16) \
intel_aes_decrypt_init_128(key, cx->expandedKey); \
else if (keysize == 24) \
intel_aes_decrypt_init_192(key, cx->expandedKey); \
else \
intel_aes_decrypt_init_256(key, cx->expandedKey); \
} \
#define native_aes_init(encrypt, keysize) \
do { \
if (encrypt) { \
if (keysize == 16) \
intel_aes_encrypt_init_128(key, cx->k.expandedKey); \
else if (keysize == 24) \
intel_aes_encrypt_init_192(key, cx->k.expandedKey); \
else \
intel_aes_encrypt_init_256(key, cx->k.expandedKey); \
} else { \
if (keysize == 16) \
intel_aes_decrypt_init_128(key, cx->k.expandedKey); \
else if (keysize == 24) \
intel_aes_decrypt_init_192(key, cx->k.expandedKey); \
else \
intel_aes_decrypt_init_256(key, cx->k.expandedKey); \
} \
} while (0)

View file

@ -62,6 +62,21 @@ intel_AES_GCM_CreateContext(void *context,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
gcmParams->ulTagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
// Limit AADLen in accordance with SP800-38D
if (sizeof(AAD_whole_len) >= 8 && AAD_whole_len > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return NULL;
}
gcm = PORT_ZNew(intel_AES_GCMContext);
if (gcm == NULL) {
return NULL;
@ -74,7 +89,7 @@ intel_AES_GCM_CreateContext(void *context,
gcm->Mlen = 0;
/* first prepare H and its derivatives for ghash */
intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->expandedKey, aes->Nr);
intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->k.expandedKey, aes->Nr);
/* Initial TAG value is zero */
_mm_storeu_si128((__m128i *)gcm->T, _mm_setzero_si128());
@ -160,6 +175,14 @@ intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
unsigned char T[AES_BLOCK_SIZE];
unsigned int j;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
if (UINT_MAX - inlen < tagBytes) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
@ -217,6 +240,14 @@ intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm,
inlen -= tagBytes;
intag = inbuf + inlen;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);

View file

@ -10,6 +10,7 @@ extern int FREEBL_InitStubs(void);
#endif
#include "loader.h"
#include "cmac.h"
#include "alghmac.h"
#include "hmacct.h"
#include "blapii.h"
@ -317,10 +318,18 @@ static const struct FREEBLVectorStr vector =
/* End of Version 3.020 */
ChaCha20_Xor
ChaCha20_Xor,
/* End of version 3.021 */
CMAC_Init,
CMAC_Create,
CMAC_Begin,
CMAC_Update,
CMAC_Finish,
CMAC_Destroy
/* End of version 3.022 */
};
const FREEBLVector*

View file

@ -2245,3 +2245,54 @@ BLAKE2B_Resurrect(unsigned char *space, void *arg)
}
return (vector->p_BLAKE2B_Resurrect)(space, arg);
}
/* == New for CMAC == */
SECStatus
CMAC_Init(CMACContext *ctx, CMACCipher type, const unsigned char *key,
unsigned int key_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_CMAC_Init)(ctx, type, key, key_len);
}
CMACContext *
CMAC_Create(CMACCipher type, const unsigned char *key, unsigned int key_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_CMAC_Create)(type, key, key_len);
}
SECStatus
CMAC_Begin(CMACContext *ctx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_CMAC_Begin)(ctx);
}
SECStatus
CMAC_Update(CMACContext *ctx, const unsigned char *data, unsigned int data_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_CMAC_Update)(ctx, data, data_len);
}
SECStatus
CMAC_Finish(CMACContext *ctx, unsigned char *result, unsigned int *result_len,
unsigned int max_result_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_CMAC_Finish)(ctx, result, result_len, max_result_len);
}
void
CMAC_Destroy(CMACContext *ctx, PRBool free_it)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
(vector->p_CMAC_Destroy)(ctx, free_it);
}

View file

@ -10,7 +10,7 @@
#include "blapi.h"
#define FREEBL_VERSION 0x0315
#define FREEBL_VERSION 0x0316
struct FREEBLVectorStr {
@ -765,6 +765,20 @@ struct FREEBLVectorStr {
/* Version 3.021 came to here */
SECStatus (*p_CMAC_Init)(CMACContext *ctx, CMACCipher type,
const unsigned char *key, unsigned int key_len);
CMACContext *(*p_CMAC_Create)(CMACCipher type, const unsigned char *key,
unsigned int key_len);
SECStatus (*p_CMAC_Begin)(CMACContext *ctx);
SECStatus (*p_CMAC_Update)(CMACContext *ctx, const unsigned char *data,
unsigned int data_len);
SECStatus (*p_CMAC_Finish)(CMACContext *ctx, unsigned char *result,
unsigned int *result_len,
unsigned int max_result_len);
void (*p_CMAC_Destroy)(CMACContext *ctx, PRBool free_it);
/* Version 3.022 came to here */
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
};

View file

@ -85,6 +85,7 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
cmac.h \
alghmac.h \
blake2b.h \
blapi.h \
@ -119,6 +120,7 @@ CSRCS = \
md2.c \
md5.c \
sha512.c \
cmac.c \
alghmac.c \
rawhash.c \
alg2268.c \
@ -162,6 +164,7 @@ CSRCS = \
ALL_CSRCS := $(CSRCS)
ALL_HDRS = \
cmac.h \
alghmac.h \
blake2b.h \
blapi.h \

View file

@ -167,6 +167,7 @@ To set an mp_int to a given value, the following functions are given:
mp_set(mp_int *mp, mp_digit d);
mp_set_int(mp_int *mp, long z);
mp_set_ulong(mp_int *mp, unsigned long z);
The mp_set() function sets the mp_int to a single digit value, while
mp_set_int() sets the mp_int to a signed long integer value.

View file

@ -727,7 +727,7 @@ static inline void
dcbzl(char *array)
{
register char *a asm("r2") = array;
__asm__ __volatile__("dcbzl %0,r0"
__asm__ __volatile__("dcbzl %0,0"
: "=r"(a)
: "0"(a));
}

View file

@ -341,33 +341,21 @@ mp_set(mp_int *mp, mp_digit d)
mp_err
mp_set_int(mp_int *mp, long z)
{
int ix;
unsigned long v = labs(z);
mp_err res;
ARGCHK(mp != NULL, MP_BADARG);
mp_zero(mp);
if (z == 0)
return MP_OKAY; /* shortcut for zero */
if (sizeof v <= sizeof(mp_digit)) {
DIGIT(mp, 0) = v;
} else {
for (ix = sizeof(long) - 1; ix >= 0; ix--) {
if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
return res;
res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
if (res != MP_OKAY)
return res;
}
/* https://bugzilla.mozilla.org/show_bug.cgi?id=1509432 */
if ((res = mp_set_ulong(mp, v)) != MP_OKAY) { /* avoids duplicated code */
return res;
}
if (z < 0)
if (z < 0) {
SIGN(mp) = NEG;
}
return MP_OKAY;
} /* end mp_set_int() */
/* }}} */
@ -1441,7 +1429,7 @@ s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
mp_digit d;
unsigned int dig, bit;
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
ARGCHK(a != NULL && b != NULL && c != NULL && m != NULL, MP_BADARG);
if (mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
return MP_RANGE;
@ -1528,7 +1516,7 @@ mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
mp_int s, x;
mp_err res;
ARGCHK(a != NULL && c != NULL, MP_BADARG);
ARGCHK(a != NULL && c != NULL && m != NULL, MP_BADARG);
if ((res = mp_init(&s)) != MP_OKAY)
return res;
@ -1581,6 +1569,8 @@ X:
int
mp_cmp_z(const mp_int *a)
{
ARGMPCHK(a != NULL);
if (SIGN(a) == NEG)
return MP_LT;
else if (USED(a) == 1 && DIGIT(a, 0) == 0)
@ -1671,7 +1661,7 @@ mp_cmp_mag(const mp_int *a, const mp_int *b)
int
mp_isodd(const mp_int *a)
{
ARGCHK(a != NULL, 0);
ARGMPCHK(a != NULL);
return (int)(DIGIT(a, 0) & 1);
@ -2015,7 +2005,7 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
mp_err k = 0;
mp_int d, f, g;
ARGCHK(a && p && c, MP_BADARG);
ARGCHK(a != NULL && p != NULL && c != NULL, MP_BADARG);
MP_DIGITS(&d) = 0;
MP_DIGITS(&f) = 0;
@ -2149,7 +2139,7 @@ s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
mp_err res;
mp_int x;
ARGCHK(a && m && c, MP_BADARG);
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@ -2187,7 +2177,7 @@ mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
mp_int g, x;
mp_err res;
ARGCHK(a && m && c, MP_BADARG);
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@ -2283,6 +2273,8 @@ s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
mp_int oddPart, evenPart; /* parts to combine via CRT. */
mp_int C2, tmp1, tmp2;
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
/*static const mp_digit d1 = 1; */
/*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
@ -2361,8 +2353,7 @@ CLEANUP:
mp_err
mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
{
ARGCHK(a && m && c, MP_BADARG);
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@ -2729,6 +2720,8 @@ mp_strerror(mp_err ec)
mp_err
s_mp_grow(mp_int *mp, mp_size min)
{
ARGCHK(mp != NULL, MP_BADARG);
if (min > ALLOC(mp)) {
mp_digit *tmp;
@ -2758,6 +2751,8 @@ s_mp_grow(mp_int *mp, mp_size min)
mp_err
s_mp_pad(mp_int *mp, mp_size min)
{
ARGCHK(mp != NULL, MP_BADARG);
if (min > USED(mp)) {
mp_err res;
@ -2877,6 +2872,8 @@ s_mp_lshd(mp_int *mp, mp_size p)
mp_err res;
unsigned int ix;
ARGCHK(mp != NULL, MP_BADARG);
if (p == 0)
return MP_OKAY;
@ -3009,6 +3006,8 @@ s_mp_mul_2(mp_int *mp)
unsigned int ix, used;
mp_digit kin = 0;
ARGCHK(mp != NULL, MP_BADARG);
/* Shift digits leftward by 1 bit */
used = MP_USED(mp);
pd = MP_DIGITS(mp);
@ -3118,6 +3117,8 @@ s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
mp_digit b_msd;
mp_err res = MP_OKAY;
ARGCHK(a != NULL && b != NULL && pd != NULL, MP_BADARG);
d = 0;
mask = DIGIT_MAX & ~(DIGIT_MAX >> 1); /* mask is msb of digit */
b_msd = DIGIT(b, USED(b) - 1);
@ -4382,6 +4383,8 @@ CLEANUP:
int
s_mp_cmp(const mp_int *a, const mp_int *b)
{
ARGMPCHK(a != NULL && b != NULL);
mp_size used_a = MP_USED(a);
{
mp_size used_b = MP_USED(b);
@ -4433,6 +4436,8 @@ IS_GT:
int
s_mp_cmp_d(const mp_int *a, mp_digit d)
{
ARGMPCHK(a != NULL);
if (USED(a) > 1)
return MP_GT;
@ -4459,6 +4464,8 @@ s_mp_ispow2(const mp_int *v)
mp_digit d;
int extra = 0, ix;
ARGMPCHK(v != NULL);
ix = MP_USED(v) - 1;
d = MP_DIGIT(v, ix); /* most significant digit of v */
@ -4786,10 +4793,7 @@ mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
int ix, jx;
unsigned int bytes;
ARGCHK(mp != NULL, MP_BADARG);
ARGCHK(str != NULL, MP_BADARG);
ARGCHK(!SIGN(mp), MP_BADARG);
ARGCHK(length > 0, MP_BADARG);
ARGCHK(mp != NULL && str != NULL && !SIGN(mp) && length > 0, MP_BADARG);
/* Constant time on the value of mp. Don't use mp_unsigned_octet_size. */
bytes = USED(mp) * MP_DIGIT_SIZE;

View file

@ -288,7 +288,14 @@ void freebl_cpuid(unsigned long op, unsigned long *eax,
#define DIGITS(MP) MP_DIGITS(MP)
#define DIGIT(MP, N) MP_DIGIT(MP, N)
/* Functions which return an mp_err value will NULL-check their arguments via
* ARGCHK(condition, return), where the caller is responsible for checking the
* mp_err return code. For functions that return an integer type, the caller
* has no way to tell if the value is an error code or a legitimate value.
* Therefore, ARGMPCHK(condition) will trigger an assertion failure on debug
* builds, but no-op in optimized builds. */
#if MP_ARGCHK == 1
#define ARGMPCHK(X) /* */
#define ARGCHK(X, Y) \
{ \
if (!(X)) { \
@ -297,9 +304,11 @@ void freebl_cpuid(unsigned long op, unsigned long *eax,
}
#elif MP_ARGCHK == 2
#include <assert.h>
#define ARGMPCHK(X) assert(X)
#define ARGCHK(X, Y) assert(X)
#else
#define ARGCHK(X, Y) /* */
#define ARGMPCHK(X) /* */
#define ARGCHK(X, Y) /* */
#endif
#ifdef CT_VERIF

View file

@ -890,7 +890,7 @@ findQfromSeed(
pqgGenType *typePtr, /* output. Generation Type used */
unsigned int *qgen_counter) /* output. q_counter */
{
HASH_HashType hashtype;
HASH_HashType hashtype = HASH_AlgNULL;
SECItem firstseed = { 0, 0, 0 };
SECItem qseed = { 0, 0, 0 };
SECStatus rv;
@ -1014,6 +1014,8 @@ makePfromQandSeed(
hashlen = HASH_ResultLen(hashtype);
outlen = hashlen * PR_BITS_PER_BYTE;
PORT_Assert(outlen > 0);
/* L - 1 = n*outlen + b */
n = (L - 1) / outlen;
b = (L - 1) % outlen;
@ -1237,7 +1239,7 @@ pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type,
unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */
unsigned int maxCount;
HASH_HashType hashtype;
HASH_HashType hashtype = HASH_AlgNULL;
SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
PLArenaPool *arena = NULL;
PQGParams *params = NULL;
@ -1628,8 +1630,8 @@ PQG_VerifyParams(const PQGParams *params,
unsigned int qseed_len;
unsigned int qgen_counter_ = 0;
SECItem pseed_ = { 0, 0, 0 };
HASH_HashType hashtype;
pqgGenType type;
HASH_HashType hashtype = HASH_AlgNULL;
pqgGenType type = FIPS186_1_TYPE;
#define CHECKPARAM(cond) \
if (!(cond)) { \
@ -1802,6 +1804,7 @@ PQG_VerifyParams(const PQGParams *params,
/* 10. P generated from (L, counter, g, SEED, Q) matches P
* in PQGParams. */
outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
PORT_Assert(outlen > 0);
n = (L - 1) / outlen;
offset = vfy->counter * (n + 1) + ((type == FIPS186_1_TYPE) ? 2 : 1);
CHECK_SEC_OK(makePfromQandSeed(hashtype, L, N, offset, g, &vfy->seed,

View file

@ -20,9 +20,19 @@
#include "gcm.h"
#include "mpi.h"
#ifdef USE_HW_AES
#include "intel-aes.h"
#if (!defined(IS_LITTLE_ENDIAN) && !defined(NSS_X86_OR_X64)) || \
(defined(__arm__) && !defined(__ARM_NEON) && !defined(__ARM_NEON__))
// not test yet on big endian platform of arm
#undef USE_HW_AES
#endif
#ifdef USE_HW_AES
#ifdef NSS_X86_OR_X64
#include "intel-aes.h"
#else
#include "aes-armv8.h"
#endif
#endif /* USE_HW_AES */
#ifdef INTEL_GCM
#include "intel-gcm.h"
#endif /* INTEL_GCM */
@ -321,7 +331,7 @@ rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int N
PRUint32 *W;
PRUint32 *pW;
PRUint32 tmp;
W = cx->expandedKey;
W = cx->k.expandedKey;
/* 1. the first Nk words contain the cipher key */
memcpy(W, key, Nk * 4);
i = Nk;
@ -353,7 +363,7 @@ rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk
rijndael_key_expansion7(cx, key, Nk);
return;
}
W = cx->expandedKey;
W = cx->k.expandedKey;
/* The first Nk words contain the input cipher key */
memcpy(W, key, Nk * 4);
i = Nk;
@ -430,7 +440,7 @@ rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int
/* ... but has the additional step of InvMixColumn,
* excepting the first and last round keys.
*/
roundkeyw = cx->expandedKey + cx->Nb;
roundkeyw = cx->k.expandedKey + cx->Nb;
for (r = 1; r < cx->Nr; ++r) {
/* each key word, roundkeyw, represents a column in the key
* matrix. Each column is multiplied by the InvMixColumn matrix.
@ -528,7 +538,7 @@ rijndael_encryptBlock128(AESContext *cx,
pOut = (unsigned char *)output;
}
#endif
roundkeyw = cx->expandedKey;
roundkeyw = cx->k.expandedKey;
/* Step 1: Add Round Key 0 to initial state */
COLUMN_0(state) = *((PRUint32 *)(pIn)) ^ *roundkeyw++;
COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw++;
@ -623,7 +633,7 @@ rijndael_decryptBlock128(AESContext *cx,
pOut = (unsigned char *)output;
}
#endif
roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
roundkeyw = cx->k.expandedKey + cx->Nb * cx->Nr + 3;
/* reverse the final key addition */
COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--;
COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw--;
@ -847,7 +857,11 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
use_hw_aes = aesni_support() && (keysize % 8) == 0;
#if defined(NSS_X86_OR_X64) || defined(USE_HW_AES)
use_hw_aes = (aesni_support() || arm_aes_support()) && (keysize % 8) == 0;
#else
use_hw_aes = PR_FALSE;
#endif
/* Nb = (block size in bits) / 32 */
cx->Nb = AES_BLOCK_SIZE / 4;
/* Nk = (key size in bits) / 32 */
@ -860,7 +874,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
#ifdef USE_HW_AES
if (use_hw_aes) {
cx->worker = (freeblCipherFunc)
intel_aes_cbc_worker(encrypt, keysize);
native_aes_cbc_worker(encrypt, keysize);
} else
#endif
{
@ -872,7 +886,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
#ifdef USE_HW_AES
if (use_hw_aes) {
cx->worker = (freeblCipherFunc)
intel_aes_ecb_worker(encrypt, keysize);
native_aes_ecb_worker(encrypt, keysize);
} else
#endif
{
@ -888,7 +902,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
}
#ifdef USE_HW_AES
if (use_hw_aes) {
intel_aes_init(encrypt, keysize);
native_aes_init(encrypt, keysize);
} else
#endif
{

View file

@ -68,7 +68,7 @@ struct AESContextStr {
__m128i keySchedule[15];
#endif
PRUint32 expandedKey[RIJNDAEL_MAX_EXP_KEY_SIZE];
};
} k;
unsigned int Nb;
unsigned int Nr;
freeblCipherFunc worker;

View file

@ -115,7 +115,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
{
unsigned char *block;
unsigned char *bp;
int padLen;
unsigned int padLen;
int i, j;
SECStatus rv;
@ -135,14 +135,15 @@ rsa_FormatOneBlock(unsigned modulusLen,
switch (blockType) {
/*
* Blocks intended for private-key operation.
*/
* Blocks intended for private-key operation.
*/
case RSA_BlockPrivate: /* preferred method */
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
* Pad is either all 0x00 or all 0xff bytes, depending on blockType.
*/
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
* padLen must be at least RSA_BLOCK_MIN_PAD_LEN (8) bytes.
* Pad is either all 0x00 or all 0xff bytes, depending on blockType.
*/
padLen = modulusLen - data->len - 3;
PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
@ -162,7 +163,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
* Pad is all non-zero random bytes.
* Pad is 8 or more non-zero random bytes.
*
* Build the block left to right.
* Fill the entire block from Pad to the end with random bytes.
@ -171,6 +172,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
* If we need more than that, refill the bytes after Pad with
* new random bytes as necessary.
*/
padLen = modulusLen - (data->len + 3);
PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
@ -236,8 +238,9 @@ rsa_FormatBlock(SECItem *result,
* The "3" below is the first octet + the second octet + the 0x00
* octet that always comes just before the ActualData.
*/
PORT_Assert(data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
if (data->len > (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))) {
return SECFailure;
}
result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;

View file

@ -436,8 +436,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
if (enc) {
while (len >= SEED_BLOCK_SIZE) {
for (n = 0; n < SEED_BLOCK_SIZE; ++n)
for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] = in[n] ^ iv[n];
}
SEED_encrypt(out, out, ks);
iv = out;
@ -447,11 +448,13 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
}
if (len) {
for (n = 0; n < len; ++n)
for (n = 0; n < len; ++n) {
out[n] = in[n] ^ iv[n];
}
for (n = len; n < SEED_BLOCK_SIZE; ++n)
for (n = len; n < SEED_BLOCK_SIZE; ++n) {
out[n] = iv[n];
}
SEED_encrypt(out, out, ks);
iv = out;
@ -462,8 +465,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
while (len >= SEED_BLOCK_SIZE) {
SEED_decrypt(in, out, ks);
for (n = 0; n < SEED_BLOCK_SIZE; ++n)
for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] ^= iv[n];
}
iv = in;
len -= SEED_BLOCK_SIZE;
@ -474,8 +478,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
if (len) {
SEED_decrypt(in, tmp, ks);
for (n = 0; n < len; ++n)
for (n = 0; n < len; ++n) {
out[n] = tmp[n] ^ iv[n];
}
iv = in;
}
@ -486,8 +491,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
memcpy(tmp, in, SEED_BLOCK_SIZE);
SEED_decrypt(in, out, ks);
for (n = 0; n < SEED_BLOCK_SIZE; ++n)
for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] ^= ivec[n];
}
memcpy(ivec, tmp, SEED_BLOCK_SIZE);
len -= SEED_BLOCK_SIZE;
@ -499,8 +505,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
memcpy(tmp, in, SEED_BLOCK_SIZE);
SEED_decrypt(tmp, tmp, ks);
for (n = 0; n < len; ++n)
for (n = 0; n < len; ++n) {
out[n] = tmp[n] ^ ivec[n];
}
memcpy(ivec, tmp, SEED_BLOCK_SIZE);
}
@ -582,6 +589,12 @@ SEED_Encrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
return SECFailure;
}
if ((inLen % SEED_BLOCK_SIZE) != 0 || maxOutLen < SEED_BLOCK_SIZE ||
maxOutLen < inLen) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (!cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@ -616,6 +629,12 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
return SECFailure;
}
if ((inLen % SEED_BLOCK_SIZE) != 0 || maxOutLen < SEED_BLOCK_SIZE ||
maxOutLen < inLen) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View file

@ -1,4 +1,4 @@
/* Copyright 2016-2017 INRIA and Microsoft Corporation
/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.