mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-23 00:47:31 +09:00
Issue #1338 - Part 2: Update NSS to 3.48-RTM
This commit is contained in:
parent
1a92143e68
commit
c57cac24e8
885 changed files with 1650639 additions and 59530 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
/*
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
},
|
||||
{
|
||||
'files': [
|
||||
'cmac.h',
|
||||
'alghmac.h',
|
||||
'blapi.h',
|
||||
'blake2b.h',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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