mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-24 01:17:34 +09:00
Update NSS to 3.48 while keeping vc2013 hackfix and no-sslkeylogfile intact.
This commit is contained in:
parent
0b9855b841
commit
171849c8e5
351 changed files with 115185 additions and 57946 deletions
|
|
@ -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
|
||||
|
|
|
|||
1169
security/nss/lib/freebl/aes-armv8.c
Normal file
1169
security/nss/lib/freebl/aes-armv8.c
Normal file
File diff suppressed because it is too large
Load diff
103
security/nss/lib/freebl/aes-armv8.h
Normal file
103
security/nss/lib/freebl/aes-armv8.h
Normal 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)
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
23
security/nss/lib/freebl/altivec-types.h
Normal file
23
security/nss/lib/freebl/altivec-types.h
Normal 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
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "blapit.h"
|
||||
#include "hasht.h"
|
||||
#include "cmac.h"
|
||||
#include "alghmac.h"
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ static PRBool arm_aes_support_ = PR_FALSE;
|
|||
static PRBool arm_sha1_support_ = PR_FALSE;
|
||||
static PRBool arm_sha2_support_ = PR_FALSE;
|
||||
static PRBool arm_pmull_support_ = PR_FALSE;
|
||||
static PRBool ppc_crypto_support_ = PR_FALSE;
|
||||
|
||||
#ifdef NSS_X86_OR_X64
|
||||
/*
|
||||
|
|
@ -137,10 +138,11 @@ CheckARMSupport()
|
|||
{
|
||||
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
|
||||
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
|
||||
char *disable_pmull = PR_GetEnvSecure("NSS_DISABLE_PMULL");
|
||||
if (getauxval) {
|
||||
long hwcaps = getauxval(AT_HWCAP);
|
||||
arm_aes_support_ = hwcaps & HWCAP_AES && disable_hw_aes == NULL;
|
||||
arm_pmull_support_ = hwcaps & HWCAP_PMULL;
|
||||
arm_pmull_support_ = hwcaps & HWCAP_PMULL && disable_pmull == NULL;
|
||||
arm_sha1_support_ = hwcaps & HWCAP_SHA1;
|
||||
arm_sha2_support_ = hwcaps & HWCAP_SHA2;
|
||||
}
|
||||
|
|
@ -204,6 +206,46 @@ GetNeonSupport()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static long
|
||||
ReadCPUInfoForHWCAP2()
|
||||
{
|
||||
FILE *cpuinfo;
|
||||
char buf[512];
|
||||
char *p;
|
||||
long hwcap2 = 0;
|
||||
|
||||
cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if (!cpuinfo) {
|
||||
return 0;
|
||||
}
|
||||
while (fgets(buf, 511, cpuinfo)) {
|
||||
if (!memcmp(buf, "Features", 8)) {
|
||||
p = strstr(buf, " aes");
|
||||
if (p && (p[4] == ' ' || p[4] == '\n')) {
|
||||
hwcap2 |= HWCAP2_AES;
|
||||
}
|
||||
p = strstr(buf, " sha1");
|
||||
if (p && (p[5] == ' ' || p[5] == '\n')) {
|
||||
hwcap2 |= HWCAP2_SHA1;
|
||||
}
|
||||
p = strstr(buf, " sha2");
|
||||
if (p && (p[5] == ' ' || p[5] == '\n')) {
|
||||
hwcap2 |= HWCAP2_SHA2;
|
||||
}
|
||||
p = strstr(buf, " pmull");
|
||||
if (p && (p[6] == ' ' || p[6] == '\n')) {
|
||||
hwcap2 |= HWCAP2_PMULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(cpuinfo);
|
||||
return hwcap2;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
void
|
||||
CheckARMSupport()
|
||||
{
|
||||
|
|
@ -216,6 +258,13 @@ CheckARMSupport()
|
|||
// AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
|
||||
// returns 0.
|
||||
long hwcaps = getauxval(AT_HWCAP2);
|
||||
#ifdef __linux__
|
||||
if (!hwcaps) {
|
||||
// Some ARMv8 devices may not implement AT_HWCAP2. So we also
|
||||
// read /proc/cpuinfo if AT_HWCAP2 is 0.
|
||||
hwcaps = ReadCPUInfoForHWCAP2();
|
||||
}
|
||||
#endif
|
||||
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
|
||||
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
|
||||
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
|
||||
|
|
@ -300,6 +349,32 @@ arm_sha2_support()
|
|||
{
|
||||
return arm_sha2_support_;
|
||||
}
|
||||
PRBool
|
||||
ppc_crypto_support()
|
||||
{
|
||||
return ppc_crypto_support_;
|
||||
}
|
||||
|
||||
#if defined(__powerpc__)
|
||||
|
||||
#include <sys/auxv.h>
|
||||
|
||||
// Defines from cputable.h in Linux kernel - PPC, letting us build on older kernels
|
||||
#ifndef PPC_FEATURE2_VEC_CRYPTO
|
||||
#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
|
||||
#endif
|
||||
|
||||
static void
|
||||
CheckPPCSupport()
|
||||
{
|
||||
char *disable_hw_crypto = PR_GetEnvSecure("NSS_DISABLE_PPC_GHASH");
|
||||
|
||||
long hwcaps = getauxval(AT_HWCAP2);
|
||||
|
||||
ppc_crypto_support_ = hwcaps & PPC_FEATURE2_VEC_CRYPTO && disable_hw_crypto == NULL;
|
||||
}
|
||||
|
||||
#endif /* __powerpc__ */
|
||||
|
||||
static PRStatus
|
||||
FreeblInit(void)
|
||||
|
|
@ -308,6 +383,8 @@ FreeblInit(void)
|
|||
CheckX86CPUSupport();
|
||||
#elif (defined(__aarch64__) || defined(__arm__))
|
||||
CheckARMSupport();
|
||||
#elif (defined(__powerpc__))
|
||||
CheckPPCSupport();
|
||||
#endif
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,8 +210,7 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
|
|||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
*outputLen = inputLen + ctx->tagLen;
|
||||
if (maxOutputLen < *outputLen) {
|
||||
if (maxOutputLen < inputLen + ctx->tagLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
@ -227,6 +226,7 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
|
|||
Poly1305Do(tag, ad, adLen, output, inputLen, block);
|
||||
PORT_Memcpy(output + inputLen, tag, ctx->tagLen);
|
||||
|
||||
*outputLen = inputLen + ctx->tagLen;
|
||||
return SECSuccess;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -254,11 +254,15 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
|
|||
return SECFailure;
|
||||
}
|
||||
ciphertextLen = inputLen - ctx->tagLen;
|
||||
*outputLen = ciphertextLen;
|
||||
if (maxOutputLen < *outputLen) {
|
||||
if (maxOutputLen < ciphertextLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
// ChaCha has a 64 octet block, with a 32-bit block counter.
|
||||
if (inputLen >= (1ULL << (6 + 32)) + ctx->tagLen) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PORT_Memset(block, 0, sizeof(block));
|
||||
// Generate a block of keystream. The first 32 bytes will be the poly1305
|
||||
|
|
@ -274,6 +278,7 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
|
|||
ChaCha20Xor(output, (uint8_t *)input, ciphertextLen, (uint8_t *)ctx->key,
|
||||
(uint8_t *)nonce, 1);
|
||||
|
||||
*outputLen = ciphertextLen;
|
||||
return SECSuccess;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
322
security/nss/lib/freebl/cmac.c
Normal file
322
security/nss/lib/freebl/cmac.c
Normal 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);
|
||||
}
|
||||
}
|
||||
47
security/nss/lib/freebl/cmac.h
Normal file
47
security/nss/lib/freebl/cmac.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ static const ECMethod kMethods[] = {
|
|||
static const ECMethod *
|
||||
ec_get_method_from_name(ECCurveName name)
|
||||
{
|
||||
int i;
|
||||
unsigned long i;
|
||||
for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
|
||||
if (kMethods[i].name == name) {
|
||||
return &kMethods[i];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,6 +27,7 @@
|
|||
},
|
||||
{
|
||||
'files': [
|
||||
'cmac.h',
|
||||
'alghmac.h',
|
||||
'blapi.h',
|
||||
'blake2b.h',
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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"', {
|
||||
|
|
|
|||
96
security/nss/lib/freebl/gcm-aarch64.c
Normal file
96
security/nss/lib/freebl/gcm-aarch64.c
Normal 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) */
|
||||
109
security/nss/lib/freebl/gcm-ppc.c
Normal file
109
security/nss/lib/freebl/gcm-ppc.c
Normal 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) */
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -62,6 +62,21 @@ intel_AES_GCM_CreateContext(void *context,
|
|||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
|
||||
gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
|
||||
gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
|
||||
gcmParams->ulTagBits != 32) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Limit AADLen in accordance with SP800-38D
|
||||
if (sizeof(AAD_whole_len) >= 8 && AAD_whole_len > (1ULL << 61) - 1) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gcm = PORT_ZNew(intel_AES_GCMContext);
|
||||
if (gcm == NULL) {
|
||||
return NULL;
|
||||
|
|
@ -74,7 +89,7 @@ intel_AES_GCM_CreateContext(void *context,
|
|||
gcm->Mlen = 0;
|
||||
|
||||
/* first prepare H and its derivatives for ghash */
|
||||
intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->expandedKey, aes->Nr);
|
||||
intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->k.expandedKey, aes->Nr);
|
||||
|
||||
/* Initial TAG value is zero */
|
||||
_mm_storeu_si128((__m128i *)gcm->T, _mm_setzero_si128());
|
||||
|
|
@ -160,6 +175,14 @@ intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
|
|||
unsigned char T[AES_BLOCK_SIZE];
|
||||
unsigned int j;
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
|
||||
if (UINT_MAX - inlen < tagBytes) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
|
|
@ -217,6 +240,14 @@ intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm,
|
|||
inlen -= tagBytes;
|
||||
intag = inbuf + inlen;
|
||||
|
||||
// GCM has a 16 octet block, with a 32-bit block counter
|
||||
// Limit in accordance with SP800-38D
|
||||
if (sizeof(inlen) > 4 &&
|
||||
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (maxout < inlen) {
|
||||
*outlen = inlen;
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ extern int FREEBL_InitStubs(void);
|
|||
#endif
|
||||
|
||||
#include "loader.h"
|
||||
#include "cmac.h"
|
||||
#include "alghmac.h"
|
||||
#include "hmacct.h"
|
||||
#include "blapii.h"
|
||||
|
|
@ -317,10 +318,18 @@ static const struct FREEBLVectorStr vector =
|
|||
|
||||
/* End of Version 3.020 */
|
||||
|
||||
ChaCha20_Xor
|
||||
ChaCha20_Xor,
|
||||
|
||||
/* End of version 3.021 */
|
||||
|
||||
CMAC_Init,
|
||||
CMAC_Create,
|
||||
CMAC_Begin,
|
||||
CMAC_Update,
|
||||
CMAC_Finish,
|
||||
CMAC_Destroy
|
||||
|
||||
/* End of version 3.022 */
|
||||
};
|
||||
|
||||
const FREEBLVector*
|
||||
|
|
|
|||
|
|
@ -2245,3 +2245,54 @@ BLAKE2B_Resurrect(unsigned char *space, void *arg)
|
|||
}
|
||||
return (vector->p_BLAKE2B_Resurrect)(space, arg);
|
||||
}
|
||||
|
||||
/* == New for CMAC == */
|
||||
SECStatus
|
||||
CMAC_Init(CMACContext *ctx, CMACCipher type, const unsigned char *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_CMAC_Init)(ctx, type, key, key_len);
|
||||
}
|
||||
|
||||
CMACContext *
|
||||
CMAC_Create(CMACCipher type, const unsigned char *key, unsigned int key_len)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return NULL;
|
||||
return (vector->p_CMAC_Create)(type, key, key_len);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CMAC_Begin(CMACContext *ctx)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_CMAC_Begin)(ctx);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CMAC_Update(CMACContext *ctx, const unsigned char *data, unsigned int data_len)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_CMAC_Update)(ctx, data, data_len);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CMAC_Finish(CMACContext *ctx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_CMAC_Finish)(ctx, result, result_len, max_result_len);
|
||||
}
|
||||
|
||||
void
|
||||
CMAC_Destroy(CMACContext *ctx, PRBool free_it)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return;
|
||||
(vector->p_CMAC_Destroy)(ctx, free_it);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "blapi.h"
|
||||
|
||||
#define FREEBL_VERSION 0x0315
|
||||
#define FREEBL_VERSION 0x0316
|
||||
|
||||
struct FREEBLVectorStr {
|
||||
|
||||
|
|
@ -765,6 +765,20 @@ struct FREEBLVectorStr {
|
|||
|
||||
/* Version 3.021 came to here */
|
||||
|
||||
SECStatus (*p_CMAC_Init)(CMACContext *ctx, CMACCipher type,
|
||||
const unsigned char *key, unsigned int key_len);
|
||||
CMACContext *(*p_CMAC_Create)(CMACCipher type, const unsigned char *key,
|
||||
unsigned int key_len);
|
||||
SECStatus (*p_CMAC_Begin)(CMACContext *ctx);
|
||||
SECStatus (*p_CMAC_Update)(CMACContext *ctx, const unsigned char *data,
|
||||
unsigned int data_len);
|
||||
SECStatus (*p_CMAC_Finish)(CMACContext *ctx, unsigned char *result,
|
||||
unsigned int *result_len,
|
||||
unsigned int max_result_len);
|
||||
void (*p_CMAC_Destroy)(CMACContext *ctx, PRBool free_it);
|
||||
|
||||
/* Version 3.022 came to here */
|
||||
|
||||
/* Add new function pointers at the end of this struct and bump
|
||||
* FREEBL_VERSION at the beginning of this file. */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,33 +341,21 @@ mp_set(mp_int *mp, mp_digit d)
|
|||
mp_err
|
||||
mp_set_int(mp_int *mp, long z)
|
||||
{
|
||||
int ix;
|
||||
unsigned long v = labs(z);
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
|
||||
mp_zero(mp);
|
||||
if (z == 0)
|
||||
return MP_OKAY; /* shortcut for zero */
|
||||
|
||||
if (sizeof v <= sizeof(mp_digit)) {
|
||||
DIGIT(mp, 0) = v;
|
||||
} else {
|
||||
for (ix = sizeof(long) - 1; ix >= 0; ix--) {
|
||||
if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
|
||||
if (res != MP_OKAY)
|
||||
return res;
|
||||
}
|
||||
/* https://bugzilla.mozilla.org/show_bug.cgi?id=1509432 */
|
||||
if ((res = mp_set_ulong(mp, v)) != MP_OKAY) { /* avoids duplicated code */
|
||||
return res;
|
||||
}
|
||||
if (z < 0)
|
||||
|
||||
if (z < 0) {
|
||||
SIGN(mp) = NEG;
|
||||
}
|
||||
|
||||
return MP_OKAY;
|
||||
|
||||
} /* end mp_set_int() */
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -1441,7 +1429,7 @@ s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
|
|||
mp_digit d;
|
||||
unsigned int dig, bit;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
|
||||
ARGCHK(a != NULL && b != NULL && c != NULL && m != NULL, MP_BADARG);
|
||||
|
||||
if (mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
|
||||
return MP_RANGE;
|
||||
|
|
@ -1528,7 +1516,7 @@ mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
|
|||
mp_int s, x;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a != NULL && c != NULL, MP_BADARG);
|
||||
ARGCHK(a != NULL && c != NULL && m != NULL, MP_BADARG);
|
||||
|
||||
if ((res = mp_init(&s)) != MP_OKAY)
|
||||
return res;
|
||||
|
|
@ -1581,6 +1569,8 @@ X:
|
|||
int
|
||||
mp_cmp_z(const mp_int *a)
|
||||
{
|
||||
ARGMPCHK(a != NULL);
|
||||
|
||||
if (SIGN(a) == NEG)
|
||||
return MP_LT;
|
||||
else if (USED(a) == 1 && DIGIT(a, 0) == 0)
|
||||
|
|
@ -1671,7 +1661,7 @@ mp_cmp_mag(const mp_int *a, const mp_int *b)
|
|||
int
|
||||
mp_isodd(const mp_int *a)
|
||||
{
|
||||
ARGCHK(a != NULL, 0);
|
||||
ARGMPCHK(a != NULL);
|
||||
|
||||
return (int)(DIGIT(a, 0) & 1);
|
||||
|
||||
|
|
@ -2015,7 +2005,7 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
|
|||
mp_err k = 0;
|
||||
mp_int d, f, g;
|
||||
|
||||
ARGCHK(a && p && c, MP_BADARG);
|
||||
ARGCHK(a != NULL && p != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
MP_DIGITS(&d) = 0;
|
||||
MP_DIGITS(&f) = 0;
|
||||
|
|
@ -2149,7 +2139,7 @@ s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
|
|||
mp_err res;
|
||||
mp_int x;
|
||||
|
||||
ARGCHK(a && m && c, MP_BADARG);
|
||||
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
|
||||
return MP_RANGE;
|
||||
|
|
@ -2187,7 +2177,7 @@ mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
|
|||
mp_int g, x;
|
||||
mp_err res;
|
||||
|
||||
ARGCHK(a && m && c, MP_BADARG);
|
||||
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
|
||||
return MP_RANGE;
|
||||
|
|
@ -2283,6 +2273,8 @@ s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
|
|||
mp_int oddPart, evenPart; /* parts to combine via CRT. */
|
||||
mp_int C2, tmp1, tmp2;
|
||||
|
||||
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
/*static const mp_digit d1 = 1; */
|
||||
/*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
|
||||
|
||||
|
|
@ -2361,8 +2353,7 @@ CLEANUP:
|
|||
mp_err
|
||||
mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
|
||||
{
|
||||
|
||||
ARGCHK(a && m && c, MP_BADARG);
|
||||
ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
|
||||
|
||||
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
|
||||
return MP_RANGE;
|
||||
|
|
@ -2729,6 +2720,8 @@ mp_strerror(mp_err ec)
|
|||
mp_err
|
||||
s_mp_grow(mp_int *mp, mp_size min)
|
||||
{
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
|
||||
if (min > ALLOC(mp)) {
|
||||
mp_digit *tmp;
|
||||
|
||||
|
|
@ -2758,6 +2751,8 @@ s_mp_grow(mp_int *mp, mp_size min)
|
|||
mp_err
|
||||
s_mp_pad(mp_int *mp, mp_size min)
|
||||
{
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
|
||||
if (min > USED(mp)) {
|
||||
mp_err res;
|
||||
|
||||
|
|
@ -2877,6 +2872,8 @@ s_mp_lshd(mp_int *mp, mp_size p)
|
|||
mp_err res;
|
||||
unsigned int ix;
|
||||
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
|
||||
if (p == 0)
|
||||
return MP_OKAY;
|
||||
|
||||
|
|
@ -3009,6 +3006,8 @@ s_mp_mul_2(mp_int *mp)
|
|||
unsigned int ix, used;
|
||||
mp_digit kin = 0;
|
||||
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
|
||||
/* Shift digits leftward by 1 bit */
|
||||
used = MP_USED(mp);
|
||||
pd = MP_DIGITS(mp);
|
||||
|
|
@ -3118,6 +3117,8 @@ s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
|
|||
mp_digit b_msd;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
ARGCHK(a != NULL && b != NULL && pd != NULL, MP_BADARG);
|
||||
|
||||
d = 0;
|
||||
mask = DIGIT_MAX & ~(DIGIT_MAX >> 1); /* mask is msb of digit */
|
||||
b_msd = DIGIT(b, USED(b) - 1);
|
||||
|
|
@ -4382,6 +4383,8 @@ CLEANUP:
|
|||
int
|
||||
s_mp_cmp(const mp_int *a, const mp_int *b)
|
||||
{
|
||||
ARGMPCHK(a != NULL && b != NULL);
|
||||
|
||||
mp_size used_a = MP_USED(a);
|
||||
{
|
||||
mp_size used_b = MP_USED(b);
|
||||
|
|
@ -4433,6 +4436,8 @@ IS_GT:
|
|||
int
|
||||
s_mp_cmp_d(const mp_int *a, mp_digit d)
|
||||
{
|
||||
ARGMPCHK(a != NULL);
|
||||
|
||||
if (USED(a) > 1)
|
||||
return MP_GT;
|
||||
|
||||
|
|
@ -4459,6 +4464,8 @@ s_mp_ispow2(const mp_int *v)
|
|||
mp_digit d;
|
||||
int extra = 0, ix;
|
||||
|
||||
ARGMPCHK(v != NULL);
|
||||
|
||||
ix = MP_USED(v) - 1;
|
||||
d = MP_DIGIT(v, ix); /* most significant digit of v */
|
||||
|
||||
|
|
@ -4786,10 +4793,7 @@ mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
|
|||
int ix, jx;
|
||||
unsigned int bytes;
|
||||
|
||||
ARGCHK(mp != NULL, MP_BADARG);
|
||||
ARGCHK(str != NULL, MP_BADARG);
|
||||
ARGCHK(!SIGN(mp), MP_BADARG);
|
||||
ARGCHK(length > 0, MP_BADARG);
|
||||
ARGCHK(mp != NULL && str != NULL && !SIGN(mp) && length > 0, MP_BADARG);
|
||||
|
||||
/* Constant time on the value of mp. Don't use mp_unsigned_octet_size. */
|
||||
bytes = USED(mp) * MP_DIGIT_SIZE;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -890,7 +890,7 @@ findQfromSeed(
|
|||
pqgGenType *typePtr, /* output. Generation Type used */
|
||||
unsigned int *qgen_counter) /* output. q_counter */
|
||||
{
|
||||
HASH_HashType hashtype;
|
||||
HASH_HashType hashtype = HASH_AlgNULL;
|
||||
SECItem firstseed = { 0, 0, 0 };
|
||||
SECItem qseed = { 0, 0, 0 };
|
||||
SECStatus rv;
|
||||
|
|
@ -1014,6 +1014,8 @@ makePfromQandSeed(
|
|||
hashlen = HASH_ResultLen(hashtype);
|
||||
outlen = hashlen * PR_BITS_PER_BYTE;
|
||||
|
||||
PORT_Assert(outlen > 0);
|
||||
|
||||
/* L - 1 = n*outlen + b */
|
||||
n = (L - 1) / outlen;
|
||||
b = (L - 1) % outlen;
|
||||
|
|
@ -1237,7 +1239,7 @@ pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type,
|
|||
unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
|
||||
unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */
|
||||
unsigned int maxCount;
|
||||
HASH_HashType hashtype;
|
||||
HASH_HashType hashtype = HASH_AlgNULL;
|
||||
SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
|
||||
PLArenaPool *arena = NULL;
|
||||
PQGParams *params = NULL;
|
||||
|
|
@ -1628,8 +1630,8 @@ PQG_VerifyParams(const PQGParams *params,
|
|||
unsigned int qseed_len;
|
||||
unsigned int qgen_counter_ = 0;
|
||||
SECItem pseed_ = { 0, 0, 0 };
|
||||
HASH_HashType hashtype;
|
||||
pqgGenType type;
|
||||
HASH_HashType hashtype = HASH_AlgNULL;
|
||||
pqgGenType type = FIPS186_1_TYPE;
|
||||
|
||||
#define CHECKPARAM(cond) \
|
||||
if (!(cond)) { \
|
||||
|
|
@ -1802,6 +1804,7 @@ PQG_VerifyParams(const PQGParams *params,
|
|||
/* 10. P generated from (L, counter, g, SEED, Q) matches P
|
||||
* in PQGParams. */
|
||||
outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
|
||||
PORT_Assert(outlen > 0);
|
||||
n = (L - 1) / outlen;
|
||||
offset = vfy->counter * (n + 1) + ((type == FIPS186_1_TYPE) ? 2 : 1);
|
||||
CHECK_SEC_OK(makePfromQandSeed(hashtype, L, N, offset, g, &vfy->seed,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue