Issue #1338 - Part 2: Update NSS to 3.48-RTM

This commit is contained in:
wolfbeast 2020-01-02 21:06:40 +01:00 committed by Roy Tam
commit c57cac24e8
885 changed files with 1650639 additions and 59530 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
@ -1013,6 +1014,10 @@ extern SECStatus ChaCha20Poly1305_Open(
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen);
extern SECStatus ChaCha20_Xor(
unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr);
/******************************************/
/*
** MD5 secure hash function

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
/*
@ -92,23 +93,32 @@ CheckX86CPUSupport()
#endif /* NSS_X86_OR_X64 */
/* clang-format off */
#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#if defined(__aarch64__) || defined(__arm__)
#ifndef __has_include
#define __has_include(x) 0
#endif
#if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \
defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)
/* This might be conflict with host compiler */
#if !defined(__ANDROID__)
#include <sys/auxv.h>
#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else
static unsigned long (*getauxval)(unsigned long) = NULL;
#define AT_HWCAP2 0
#define AT_HWCAP 0
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/
#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */
#ifndef AT_HWCAP2
#define AT_HWCAP2 26
#endif
#ifndef AT_HWCAP
#define AT_HWCAP 16
#endif
#endif /* defined(__aarch64__) || defined(__arm__) */
/* clang-format on */
#if defined(__aarch64__) && !defined(__ANDROID__)
#if defined(__aarch64__)
// Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES
#define HWCAP_AES (1 << 3)
@ -128,19 +138,20 @@ 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;
}
/* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL;
}
#endif /* defined(__aarch64__) && !defined(__ANDROID__) */
#endif /* defined(__aarch64__) */
#if defined(__arm__) && !defined(__ANDROID__)
#if defined(__arm__)
// Defines from hwcap.h in Linux kernel - ARM
/*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
@ -165,23 +176,105 @@ CheckARMSupport()
#define HWCAP2_SHA2 (1 << 3)
#endif
PRBool
GetNeonSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
if (disable_arm_neon) {
return PR_FALSE;
}
#if defined(__ARM_NEON) || defined(__ARM_NEON__)
// Compiler generates NEON instruction as default option.
// If no getauxval, compiler generate NEON instruction by default,
// we should allow NOEN support.
return PR_TRUE;
#elif !defined(__ANDROID__)
// Android's cpu-features.c detects features by the following logic
//
// - Call getauxval(AT_HWCAP)
// - Parse /proc/self/auxv if getauxval is nothing or returns 0
// - Parse /proc/cpuinfo if both cannot detect features
//
// But we don't use it for Android since Android document
// (https://developer.android.com/ndk/guides/cpu-features) says
// one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator)
// are mistaken for IDIV.
if (getauxval) {
return (getauxval(AT_HWCAP) & HWCAP_NEON);
}
#endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */
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()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
if (getauxval) {
// Android's cpu-features.c uses AT_HWCAP2 for newer features.
// AT_HWCAP2 is implemented on newer devices / kernel, so we can trust
// it since cpu-features.c doesn't have workaround / fallback.
// Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If
// 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;
arm_sha2_support_ = hwcaps & HWCAP2_SHA2;
arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL;
}
arm_neon_support_ = GetNeonSupport();
}
#endif /* defined(__arm__) && !defined(__ANDROID__) */
#endif /* defined(__arm__) */
// Enable when Firefox can use it.
// Enable when Firefox can use it for Android API 16 and 17.
// #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__))
// #include <cpu-features.h>
// void
@ -256,14 +349,42 @@ 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)
{
#ifdef NSS_X86_OR_X64
CheckX86CPUSupport();
#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
#elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport();
#elif (defined(__powerpc__))
CheckPPCSupport();
#endif
return PR_SUCCESS;
}

View file

@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
#endif
}
#ifndef NSS_DISABLE_CHACHAPOLY
void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr)
@ -167,6 +168,25 @@ ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr);
}
}
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
{
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(len) > 4 && len >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
ChaCha20Xor(output, (uint8_t *)block, len, (uint8_t *)k,
(uint8_t *)nonce, ctr);
return SECSuccess;
#endif
}
SECStatus
ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
@ -185,8 +205,12 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
*outputLen = inputLen + ctx->tagLen;
if (maxOutputLen < *outputLen) {
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(inputLen) > 4 && inputLen >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxOutputLen < inputLen + ctx->tagLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@ -202,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
}
@ -229,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
@ -249,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

@ -22,7 +22,7 @@ swap8b(PRUint64 value)
return (value);
}
#elif !defined(_MSC_VER)
#elif defined(IS_LITTLE_ENDIAN) && !defined(_MSC_VER) && !__has_builtin(__builtin_bswap64) && !((defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
PRUint64
swap8b(PRUint64 x)

View file

@ -11,6 +11,11 @@
#include <stdlib.h>
#include "prtypes.h"
/* For non-clang platform */
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG)
@ -29,11 +34,17 @@
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x)
/* gcc doesn't have __has_builtin, but it does have __builtin_bswap64 */
#elif __has_builtin(__builtin_bswap64) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#define FREEBL_HTONLL(x) __builtin_bswap64(x)
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value);
@ -48,4 +59,8 @@ PRUint64 swap8b(PRUint64 x);
#endif /* _MSC_VER */
#endif /* HAVE_LONG_LONG */
#else /* IS_LITTLE_ENDIAN */
#define FREEBL_HTONLL(x) (x)
#endif
#endif /* HAVE_LONG_LONG */

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

@ -210,7 +210,8 @@ DH_Derive(SECItem *publicValue,
unsigned int len = 0;
unsigned int nb;
unsigned char *secret = NULL;
if (!publicValue || !prime || !privateValue || !derivedSecret) {
if (!publicValue || !publicValue->len || !prime || !prime->len ||
!privateValue || !privateValue->len || !derivedSecret) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}

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];
@ -202,8 +202,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
#endif
MP_DIGITS(&k) = 0;
if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0) ||
!ecParams->name) {
if (!ecParams || ecParams->name == ECCurve_noName ||
!privKey || !privKeyBytes || privKeyLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@ -391,7 +391,7 @@ EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey)
int len;
unsigned char *privKeyBytes = NULL;
if (!ecParams) {
if (!ecParams || ecParams->name == ECCurve_noName || !privKey) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@ -430,7 +430,8 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
mp_err err = MP_OKAY;
int len;
if (!ecParams || !publicValue || !ecParams->name) {
if (!ecParams || ecParams->name == ECCurve_noName ||
!publicValue || !publicValue->len) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@ -536,8 +537,9 @@ ECDH_Derive(SECItem *publicValue,
int i;
#endif
if (!publicValue || !ecParams || !privateValue || !derivedSecret ||
!ecParams->name) {
if (!publicValue || !publicValue->len ||
!ecParams || ecParams->name == ECCurve_noName ||
!privateValue || !privateValue->len || !derivedSecret) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}

File diff suppressed because it is too large Load diff

View file

@ -114,6 +114,9 @@ ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P)
}
px = P->data;
}
if (k->len != 32) {
return SECFailure;
}
SECStatus rv = ec_Curve25519_mul(X->data, k->data, px);
if (NSS_SecureMemcmpZero(X->data, X->len) == 0) {

View file

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

View file

@ -15,8 +15,10 @@
#include "seccomon.h" /* Required for RSA and DSA. */
#include "secerr.h"
#include "prtypes.h"
#include "secitem.h"
#include "pkcs11t.h"
#include "ec.h" /* Required for ECDSA */
#include "ec.h" /* Required for EC */
/*
* different platforms have different ways of calling and initial entry point
@ -288,6 +290,8 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
/* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
/* AES Known Ciphertext (128-bit key). */
static const PRUint8 aes_ecb128_known_ciphertext[] = {
0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
@ -299,6 +303,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
};
static const PRUint8 aes_gcm128_known_ciphertext[] = {
0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
};
/* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
@ -310,6 +321,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
};
static const PRUint8 aes_gcm192_known_ciphertext[] = {
0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
};
/* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
@ -321,18 +339,29 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
};
static const PRUint8 aes_gcm256_known_ciphertext[] = {
0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
};
const PRUint8 *aes_ecb_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
const PRUint8 *aes_cbc_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
const PRUint8 *aes_gcm_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
/* AES variables. */
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context;
unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted;
CK_GCM_PARAMS gcmParams;
SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */
@ -455,6 +484,69 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Encryption Test. */
/******************************************************/
gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_TRUE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
&aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
(PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Decryption Test. */
/******************************************************/
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_FALSE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
&aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
(PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
"Firefox and ThunderBird are awesome!"
};
unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
unsigned char sig[2 * MAX_ECKEY_LEN];
SECItem signature, digest;
ECPrivateKey *ecdsa_private_key = NULL;
@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
/* ECDSA Single-Round Known Answer Signature Test. */
/***************************************************/
ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
digest.type = siBuffer;
digest.data = sha1;
digest.len = SHA1_LENGTH;
digest.data = sha256;
digest.len = SHA256_LENGTH;
memset(sig, 0, sizeof sig);
signature.type = siBuffer;
@ -1181,10 +1273,83 @@ loser:
}
static SECStatus
freebl_fips_ECDSA_PowerUpSelfTest()
freebl_fips_ECDH_Test(ECParams *ecparams)
{
/* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
/* ECDH Known result (reused old CAVS vector) */
static const PRUint8 ecdh_known_pub_key_1[] = {
EC_POINT_FORM_UNCOMPRESSED,
/* pubX */
0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
/* pubY */
0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
};
static const PRUint8 ecdh_known_priv_key_2[] = {
0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
};
static const PRUint8 ecdh_known_hash_result[] = {
0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
};
SECItem ecdh_priv_2, ecdh_pub_1;
SECItem ZZ = { 0, 0, 0 };
SECStatus ecdhStatus = SECSuccess;
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
/* Generates a new EC key pair. The private key is a supplied
* random value (in seed) and the public key is the result of
* performing a scalar point multiplication of that value with
* the curve's base point.
*/
ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
if (ecdhStatus != SECSuccess) {
goto loser;
}
ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (ecdhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
sizeof(ecdh_known_hash_result)) != 0) {
ecdhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (ecdhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_EC_PowerUpSelfTest()
{
/* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
static const unsigned char p256_prime[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@ -1217,7 +1382,7 @@ freebl_fips_ECDSA_PowerUpSelfTest()
static const unsigned char p256_encoding[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
};
static const ECParams ecdsa_known_P256_Params = {
static const ECParams ec_known_P256_Params = {
NULL, ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest()
0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
};
ECParams ecparams;
@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest()
SECStatus rv;
/* ECDSA GF(p) prime field curve test */
ecparams = ecdsa_known_P256_Params;
ecparams = ec_known_P256_Params;
rv = freebl_fips_ECDSA_Test(&ecparams,
ecdsa_known_P256_signature,
sizeof ecdsa_known_P256_signature);
if (rv != SECSuccess) {
return (SECFailure);
}
/* ECDH GF(p) prime field curve test */
rv = freebl_fips_ECDH_Test(&ecparams);
if (rv != SECSuccess) {
return (SECFailure);
}
return (SECSuccess);
}
@ -1417,6 +1587,138 @@ freebl_fips_DSA_PowerUpSelfTest(void)
return (SECSuccess);
}
static SECStatus
freebl_fips_DH_PowerUpSelfTest(void)
{
/* DH Known P (2048-bits) */
static const PRUint8 dh_known_P[] = {
0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
};
static const PRUint8 dh_known_Y_1[] = {
0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
};
static const PRUint8 dh_known_x_2[] = {
0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
};
static const PRUint8 dh_known_hash_result[] = {
0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
};
/* DH variables. */
SECStatus dhStatus;
SECItem dh_prime;
SECItem dh_pub_key_1;
SECItem dh_priv_key_2;
SECItem ZZ = { 0, 0, 0 };
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
dh_prime.data = (PRUint8 *)dh_known_P;
dh_prime.len = sizeof(dh_known_P);
dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
dh_pub_key_1.len = sizeof(dh_known_Y_1);
dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
dh_priv_key_2.len = sizeof(dh_known_x_2);
/* execute the derive */
dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
if (dhStatus != SECSuccess) {
goto loser;
}
dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (dhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
sizeof(dh_known_hash_result)) != 0) {
dhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (dhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_RNG_PowerUpSelfTest(void)
{
@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
return rv;
/* NOTE: RSA can only be tested in full freebl. It requires access to
* the locking primitives */
* the locking primitives */
/* RSA Power-Up SelfTest(s). */
rv = freebl_fips_RSA_PowerUpSelfTest();
@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess)
return rv;
/* ECDSA Power-Up SelfTest(s). */
rv = freebl_fips_ECDSA_PowerUpSelfTest();
/* DH Power-Up SelfTest(s). */
rv = freebl_fips_DH_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* EC Power-Up SelfTest(s). */
rv = freebl_fips_EC_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;

View file

@ -76,11 +76,11 @@
'__SSSE3__',
],
}],
[ 'OS=="android"', {
# On Android we can't use any of the hardware acceleration :(
'defines!': [
'__ARM_NEON__',
'__ARM_NEON',
[ 'target_arch=="arm"', {
# Gecko doesn't support non-NEON platform on Android, but tier-3
# platform such as Linux/arm will need it
'cflags_mozilla': [
'-mfpu=neon'
],
}],
],
@ -107,7 +107,7 @@
],
}],
# macOS build doesn't use cflags.
[ 'OS=="mac"', {
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mpclmul', '-maes'
@ -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());
@ -143,6 +158,7 @@ loser:
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
@ -159,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);
@ -216,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"
@ -313,10 +314,22 @@ static const struct FREEBLVectorStr vector =
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
BLAKE2B_Resurrect
BLAKE2B_Resurrect,
/* End of Version 3.020 */
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

@ -2060,6 +2060,16 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
return (vector->p_EC_CopyParams)(arena, dstParams, srcParams);
}
SECStatus
ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
return SECFailure;
}
return (vector->p_ChaCha20_Xor)(output, block, len, k, nonce, ctr);
}
SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
const unsigned char *key, unsigned int keyLen,
@ -2235,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 0x0314
#define FREEBL_VERSION 0x0316
struct FREEBLVectorStr {
@ -759,6 +759,26 @@ struct FREEBLVectorStr {
/* Version 3.020 came to here */
SECStatus (*p_ChaCha20_Xor)(unsigned char *output, const unsigned char *block,
unsigned int len, const unsigned char *k,
const unsigned char *nonce, PRUint32 ctr);
/* 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;
@ -2063,7 +2053,10 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
}
}
if (res >= 0) {
while (MP_SIGN(c) != MP_ZPOS) {
if (mp_cmp_mag(c, p) >= 0) {
MP_CHECKOK(mp_div(c, p, NULL, c));
}
if (MP_SIGN(c) != MP_ZPOS) {
MP_CHECKOK(mp_add(c, p, c));
}
res = k;
@ -2146,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;
@ -2184,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;
@ -2280,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 }; */
@ -2358,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;
@ -2726,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;
@ -2755,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;
@ -2874,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;
@ -3006,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);
@ -3115,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);
@ -4379,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);
@ -4430,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;
@ -4456,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 */
@ -4783,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

@ -491,11 +491,11 @@ cleanup:
** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
** steps 16 through 34 of FIPS 186-2 C.6
*/
#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
static SECStatus
makePrimefromPrimesShaweTaylor(
HASH_HashType hashtype, /* selected Hashing algorithm */
unsigned int length, /* input. Length of prime in bits. */
unsigned int seedlen, /* input seed length in bits */
mp_int *c0, /* seed prime */
mp_int *q, /* sub prime, can be 1 */
mp_int *prime, /* output. */
@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor(
old_counter = *prime_gen_counter;
/*
** Comment: Generate a pseudorandom integer x in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 6/18 x = 0
*/
@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor(
for (i = 0; i < iterations; i++) {
/* is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 8/20 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/*
** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
**
@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor(
x[offset] = (mask & x[offset]) | bit;
/*
** Comment: Generate a candidate prime c in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 10 t = ceiling(x/(2q(p0)))
** Step 22 t = ceiling(x/(2(c0)))
@ -624,7 +623,7 @@ step_23:
/* t = 2**(length-1) + 2qc0 -1 */
CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
/* t = floor((2**(length-1)+2qc0 -1)/2qco)
* = ceil(2**(lenght-2)/2qc0) */
* = ceil(2**(length-2)/2qc0) */
CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
@ -645,13 +644,11 @@ step_23:
** NOTE: we reuse the x array for 'a' initially.
*/
for (i = 0; i < iterations; i++) {
/* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 16/28 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/* Step 17/29 a = 2 + (a mod (c-3)). */
CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
@ -742,6 +739,7 @@ makePrimefromSeedShaweTaylor(
int hashlen = HASH_ResultLen(hashtype);
int outlen = hashlen * PR_BITS_PER_BYTE;
int offset;
int seedlen = input_seed->len * 8; /*seedlen is in bits */
unsigned char bit, mask;
unsigned char x[HASH_LENGTH_MAX * 2];
mp_digit dummy;
@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor(
goto cleanup;
}
/* Steps 16-34 */
rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
prime, prime_seed, prime_gen_counter);
goto cleanup; /* we're done, one way or the other */
}
@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor(
step_5:
/* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
MAX_ST_SEED_BITS, &x[hashlen]));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
for (i = 0; i < hashlen; i++) {
x[i] = x[i] ^ x[i + hashlen];
}
@ -817,7 +814,7 @@ step_5:
/* Step 8 prime_gen_counter = prime_gen_counter + 1 */
(*prime_gen_counter)++;
/* Step 9 prime_seed = prime_seed + 2 */
CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
/* Step 10 Perform deterministic primality test on c. For example, since
** c is small, it's primality can be tested by trial division, See
** See Appendic C.7.
@ -890,9 +887,10 @@ findQfromSeed(
mp_int *Q_, /* output. */
unsigned int *qseed_len, /* output */
HASH_HashType *hashtypePtr, /* output. Hash uses */
pqgGenType *typePtr) /* output. Generation Type used */
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;
@ -964,6 +962,7 @@ findQfromSeed(
*qseed_len = qseed.len;
*hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE;
*qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE);
return SECSuccess;
}
@ -1015,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;
@ -1238,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;
@ -1388,19 +1389,26 @@ step_5:
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed, &pgen_counter));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
&p0, &Q, &P, &pseed, &pgen_counter));
/* combine all the seeds */
seed->len = firstseed.len + qseed.len + pseed.len;
if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
goto cleanup;
}
/* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps.
* we want to make sure those are added back in so the individual seed lengths are predictable from
* the overall seed length */
seed->len = firstseed.len * 3;
seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
if (seed->data == NULL) {
goto cleanup;
}
PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
counter = 0; /* (qgen_counter << 16) | pgen_counter; */
PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
counter = (qgen_counter << 16) | pgen_counter;
/* we've generated both P and Q now, skip to generating G */
goto generate_G;
@ -1620,9 +1628,10 @@ PQG_VerifyParams(const PQGParams *params,
int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */
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)) { \
@ -1699,48 +1708,55 @@ PQG_VerifyParams(const PQGParams *params,
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */
/* 7. counter < 4*L */
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
/* 8. g >= N and g < 2*L (g is length of seed in bits) */
g = vfy->seed.len * 8;
CHECKPARAM(g >= N && g < counter_max / 2);
/* step 7 and 8 are delayed until we determine which type of generation
* was used */
/* 9. Q generated from SEED matches Q in PQGParams. */
/* This function checks all possible hash and generation types to
* find a Q_ which matches Q. */
g = vfy->seed.len * 8;
CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
&hashtype, &type) == SECSuccess);
&hashtype, &type, &qgen_counter_) == SECSuccess);
CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
/* now we can do steps 7 & 8*/
if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
CHECKPARAM(g >= N && g < counter_max / 2);
}
if (type == FIPS186_3_ST_TYPE) {
SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 };
unsigned int first_seed_len;
unsigned int pgen_counter = 0;
unsigned int pgen_counter_ = 0;
unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
unsigned int pgen_counter = (vfy->counter) & 0xffff;
/* extract pseed and qseed from domain_parameter_seed, which is
* first_seed || pseed || qseed. qseed is first_seed + small_integer
* pseed is qseed + small_integer. This means most of the time
* mod the length of first_seed. pseed is qseed + small_integer mod
* the length of first_seed. This means most of the time
* first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
* pseed.len will be one greater than first_seed.len, so we can
* depend on the fact that
* first_seed.len = floor(domain_parameter_seed.len/3).
* findQfromSeed returned qseed.len, so we can calculate pseed.len as
* pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
* this is probably over kill, since 99.999% of the time they will all
* be equal.
*
* With the lengths, we can now find the offsets;
* pseed.len will be smaller because mpi clamps them. pqgGen
* automatically adds the zero pad back though, so we can depend
* domain_parameter_seed.len to be a multiple of three. We only have
* to deal with the fact that the returned seeds from our functions
* could be shorter.
* first_seed.len = domain_parameter_seed.len/3
* We can now find the offsets;
* first_seed.data = domain_parameter_seed.data + 0
* pseed.data = domain_parameter_seed.data + first_seed.len
* qseed.data = domain_parameter_seed.data
* + domain_paramter_seed.len - qseed.len
*
* We deal with pseed possibly having zero pad in the pseed check later.
*/
first_seed_len = vfy->seed.len / 3;
CHECKPARAM(qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 > N - 1);
CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 < counter_max / 2);
CHECKPARAM(first_seed_len >= qseed_len);
qseed.len = qseed_len;
qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
pseed.len = first_seed_len;
pseed.data = vfy->seed.data + first_seed_len;
/*
@ -1752,14 +1768,34 @@ PQG_VerifyParams(const PQGParams *params,
** (ST_Random_Prime((ceil(length/2)+1, input_seed)
*/
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed_, &pgen_counter));
&qseed, &p0, &pseed_, &pgen_counter_));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
&p0, &Q_, &P_, &pseed_, &pgen_counter));
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
&p0, &Q_, &P_, &pseed_, &pgen_counter_));
CHECKPARAM(mp_cmp(&P, &P_) == 0);
/* make sure pseed wasn't tampered with (since it is part of
* calculating G) */
if (pseed.len > pseed_.len) {
/* handle the case of zero pad for pseed */
int extra = pseed.len - pseed_.len;
int i;
for (i = 0; i < extra; i++) {
if (pseed.data[i] != 0) {
*result = SECFailure;
goto cleanup;
}
}
pseed.data += extra;
pseed.len -= extra;
/* the rest is handled in the normal compare below */
}
CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
if (vfy->counter != -1) {
CHECKPARAM(pgen_counter < counter_max);
CHECKPARAM(qgen_counter < counter_max);
CHECKPARAM((pgen_counter_ == pgen_counter));
CHECKPARAM((qgen_counter_ == qgen_counter));
}
} else if (vfy->counter == -1) {
/* If counter is set to -1, we are really only verifying G, skip
* the remainder of the checks for P */
@ -1768,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
{
@ -1032,13 +1046,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv,
void
AES_DestroyContext(AESContext *cx, PRBool freeit)
{
void *mem = cx->mem;
if (cx->worker_cx && cx->destroy) {
(*cx->destroy)(cx->worker_cx, PR_TRUE);
cx->worker_cx = NULL;
cx->destroy = NULL;
}
PORT_Memset(cx, 0, sizeof(AESContext));
if (freeit) {
PORT_Free(cx->mem);
PORT_Free(mem);
} else {
/* if we are not freeing the context, restore mem, We may get called
* again to actually free the context */
cx->mem = mem;
}
}

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

@ -99,6 +99,7 @@ swap4b(PRUint32 value)
defined(__ARM_ARCH_7__) || \
defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)))
#if defined(IS_LITTLE_ENDIAN)
static __inline__ PRUint32
swap4b(PRUint32 value)
{
@ -109,6 +110,7 @@ swap4b(PRUint32 value)
return ret;
}
#define SHA_HTONL(x) swap4b(x)
#endif
#endif /* x86 family */

View file

@ -32,7 +32,7 @@ RNG_SystemRNG(void *dest, size_t maxLen)
size_t fileBytes = 0;
unsigned char *buffer = dest;
#if defined(__OpenBSD__) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
int result;
while (fileBytes < maxLen) {

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.