summaryrefslogtreecommitdiff
path: root/nss/lib/freebl
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/freebl')
-rw-r--r--nss/lib/freebl/Makefile17
-rw-r--r--nss/lib/freebl/blapi.h15
-rw-r--r--nss/lib/freebl/blapii.h9
-rw-r--r--nss/lib/freebl/blapit.h1
-rw-r--r--nss/lib/freebl/blinit.c119
-rw-r--r--nss/lib/freebl/det_rng.c82
-rw-r--r--nss/lib/freebl/dh.c13
-rw-r--r--nss/lib/freebl/drbg.c47
-rw-r--r--nss/lib/freebl/ec.c39
-rw-r--r--nss/lib/freebl/ecdecode.c125
-rw-r--r--nss/lib/freebl/ecl/README104
-rw-r--r--nss/lib/freebl/ecl/curve25519_64.c2
-rw-r--r--nss/lib/freebl/ecl/ecl-curve.h218
-rw-r--r--nss/lib/freebl/ecl/ecl-priv.h7
-rw-r--r--nss/lib/freebl/ecl/ecl.c127
-rw-r--r--nss/lib/freebl/ecl/ecl.h13
-rw-r--r--nss/lib/freebl/ecl/ecl_curve.c93
-rw-r--r--nss/lib/freebl/ecl/eclt.h30
-rw-r--r--nss/lib/freebl/ecl/ecp_25519.c3
-rw-r--r--nss/lib/freebl/ecl/ecp_jm.c11
-rw-r--r--nss/lib/freebl/ecl/tests/ec_naft.c121
-rw-r--r--nss/lib/freebl/ecl/tests/ecp_test.c409
-rw-r--r--nss/lib/freebl/ecl/uint128.c5
-rw-r--r--nss/lib/freebl/exports.gyp1
-rw-r--r--nss/lib/freebl/freebl.gyp268
-rw-r--r--nss/lib/freebl/freebl_base.gypi201
-rw-r--r--nss/lib/freebl/ldvector.c6
-rw-r--r--nss/lib/freebl/loader.c8
-rw-r--r--nss/lib/freebl/loader.h6
-rw-r--r--nss/lib/freebl/manifest.mn4
-rw-r--r--nss/lib/freebl/mpi/README3
-rw-r--r--nss/lib/freebl/mpi/mpi-config.h4
-rw-r--r--nss/lib/freebl/mpi/mpi.c52
-rw-r--r--nss/lib/freebl/mpi/mpi.h2
-rw-r--r--nss/lib/freebl/mpi/mpprime.c5
-rw-r--r--nss/lib/freebl/mpi/mpprime.h7
-rw-r--r--nss/lib/freebl/os2_rand.c334
-rw-r--r--nss/lib/freebl/rijndael.c67
-rw-r--r--nss/lib/freebl/rsa.c19
-rw-r--r--nss/lib/freebl/rsapkcs.c221
-rw-r--r--nss/lib/freebl/sysrand.c37
-rw-r--r--nss/lib/freebl/unix_rand.c276
-rw-r--r--nss/lib/freebl/unix_urandom.c50
43 files changed, 1136 insertions, 2045 deletions
diff --git a/nss/lib/freebl/Makefile b/nss/lib/freebl/Makefile
index 0ce1425..aa02f4b 100644
--- a/nss/lib/freebl/Makefile
+++ b/nss/lib/freebl/Makefile
@@ -232,8 +232,6 @@ ifeq ($(CPU_ARCH),x86)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT
DEFINES += -DMP_IS_LITTLE_ENDIAN
- # The floating point ECC code doesn't work on Linux x86 (bug 311432).
- #ECL_USE_FP = 1
endif
ifeq ($(CPU_ARCH),arm)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
@@ -430,7 +428,6 @@ ifeq ($(CPU_ARCH),sparc)
ASFILES = mpv_sparcv8.s montmulfv8.s
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
- ECL_USE_FP = 1
endif
ifdef USE_ABI64_INT
# this builds for Sparc v9a pure 64-bit architecture
@@ -443,7 +440,6 @@ ifeq ($(CPU_ARCH),sparc)
ASFILES = mpv_sparcv9.s montmulfv9.s
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
- ECL_USE_FP = 1
endif
else
@@ -491,16 +487,7 @@ else
endif
endif
endif # Solaris for non-sparc family CPUs
-endif # target == SunOS
-
-ifndef NSS_DISABLE_ECC
- ifdef ECL_USE_FP
- #enable floating point ECC code
- DEFINES += -DECL_USE_FP
- ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
- ECL_HDRS += ecp_fp.h
- endif
-endif
+endif # target == SunO
# poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
# in GCC 4.6.0.
@@ -601,7 +588,7 @@ $(ECL_OBJS): $(ECL_HDRS)
-$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c os2_rand.c
+$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
diff --git a/nss/lib/freebl/blapi.h b/nss/lib/freebl/blapi.h
index 38c3a9f..592624b 100644
--- a/nss/lib/freebl/blapi.h
+++ b/nss/lib/freebl/blapi.h
@@ -1429,8 +1429,6 @@ extern SECStatus RNG_RandomUpdate(const void *data, size_t bytes);
*/
extern SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len);
-extern SECStatus RNG_ResetForFuzzing(void);
-
/* Destroy the global RNG context. After a call to RNG_RNGShutdown()
** a call to RNG_RNGInit() is required in order to use the generator again,
** along with seed data (see the comment above RNG_RNGInit()).
@@ -1469,6 +1467,12 @@ FIPS186Change_ReduceModQForDSA(const unsigned char *w,
const unsigned char *q,
unsigned char *xj);
+/* To allow NIST KAT tests */
+extern SECStatus
+PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *nonce, unsigned int nonce_len,
+ const PRUint8 *personal_string, unsigned int ps_len);
+
/*
* The following functions are for FIPS poweron self test and FIPS algorithm
* testing.
@@ -1599,7 +1603,6 @@ extern const SECHashObject *HASH_GetRawHashObject(HASH_HashType hashType);
extern void BL_SetForkState(PRBool forked);
-#ifndef NSS_DISABLE_ECC
/*
** pepare an ECParam structure from DEREncoded params
*/
@@ -1609,7 +1612,11 @@ extern SECStatus EC_DecodeParams(const SECItem *encodedParams,
ECParams **ecparams);
extern SECStatus EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
const ECParams *srcParams);
-#endif
+
+/*
+ * use the internal table to get the size in bytes of a single EC point
+ */
+extern int EC_GetPointSize(const ECParams *params);
SEC_END_PROTOS
diff --git a/nss/lib/freebl/blapii.h b/nss/lib/freebl/blapii.h
index 6ad2e28..0087c78 100644
--- a/nss/lib/freebl/blapii.h
+++ b/nss/lib/freebl/blapii.h
@@ -9,6 +9,7 @@
#define _BLAPII_H_
#include "blapit.h"
+#include "mpi.h"
/* max block size of supported block ciphers */
#define MAX_BLOCK_SIZE 16
@@ -58,4 +59,12 @@ SEC_END_PROTOS
#undef HAVE_NO_SANITIZE_ATTR
+SECStatus RSA_Init();
+SECStatus generate_prime(mp_int *prime, int primeLen);
+
+/* Freebl state. */
+PRBool aesni_support();
+PRBool clmul_support();
+PRBool avx_support();
+
#endif /* _BLAPII_H_ */
diff --git a/nss/lib/freebl/blapit.h b/nss/lib/freebl/blapit.h
index 7cf8fc6..2a17b5f 100644
--- a/nss/lib/freebl/blapit.h
+++ b/nss/lib/freebl/blapit.h
@@ -377,7 +377,6 @@ struct ECParamsStr {
SECItem DEREncoding;
ECCurveName name;
SECItem curveOID;
- int pointSize;
};
typedef struct ECParamsStr ECParams;
diff --git a/nss/lib/freebl/blinit.c b/nss/lib/freebl/blinit.c
new file mode 100644
index 0000000..d7f2ec5
--- /dev/null
+++ b/nss/lib/freebl/blinit.c
@@ -0,0 +1,119 @@
+/* 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 "blapii.h"
+#include "mpi.h"
+#include "secerr.h"
+#include "prtypes.h"
+#include "prinit.h"
+#include "prenv.h"
+
+#if defined(_MSC_VER) && !defined(_M_IX86)
+#include <intrin.h> /* for _xgetbv() */
+#endif
+
+static PRCallOnceType coFreeblInit;
+
+/* State variables. */
+static PRBool aesni_support_ = PR_FALSE;
+static PRBool clmul_support_ = PR_FALSE;
+static PRBool avx_support_ = PR_FALSE;
+
+#ifdef NSS_X86_OR_X64
+/*
+ * Adapted from the example code in "How to detect New Instruction support in
+ * the 4th generation Intel Core processor family" by Max Locktyukhin.
+ *
+ * XGETBV:
+ * Reads an extended control register (XCR) specified by ECX into EDX:EAX.
+ */
+static PRBool
+check_xcr0_ymm()
+{
+ PRUint32 xcr0;
+#if defined(_MSC_VER)
+#if defined(_M_IX86)
+ __asm {
+ mov ecx, 0
+ xgetbv
+ mov xcr0, eax
+ }
+#else
+ xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */
+#endif /* _M_IX86 */
+#else /* _MSC_VER */
+ /* Old OSX compilers don't support xgetbv. Use byte form. */
+ __asm__(".byte 0x0F, 0x01, 0xd0"
+ : "=a"(xcr0)
+ : "c"(0)
+ : "%edx");
+#endif /* _MSC_VER */
+ /* Check if xmm and ymm state are enabled in XCR0. */
+ return (xcr0 & 6) == 6;
+}
+
+#define ECX_AESNI (1 << 25)
+#define ECX_CLMUL (1 << 1)
+#define ECX_XSAVE (1 << 26)
+#define ECX_OSXSAVE (1 << 27)
+#define ECX_AVX (1 << 28)
+#define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX)
+
+void
+CheckX86CPUSupport()
+{
+ unsigned long eax, ebx, ecx, edx;
+ char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
+ char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL");
+ char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX");
+ freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
+ aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL);
+ clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL);
+ /* For AVX we check AVX, OSXSAVE, and XSAVE
+ * as well as XMM and YMM state. */
+ avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() &&
+ disable_avx == NULL;
+}
+#endif /* NSS_X86_OR_X64 */
+
+PRBool
+aesni_support()
+{
+ return aesni_support_;
+}
+PRBool
+clmul_support()
+{
+ return clmul_support_;
+}
+PRBool
+avx_support()
+{
+ return avx_support_;
+}
+
+static PRStatus
+FreeblInit(void)
+{
+#ifdef NSS_X86_OR_X64
+ CheckX86CPUSupport();
+#endif
+ return PR_SUCCESS;
+}
+
+SECStatus
+BL_Init()
+{
+ if (PR_CallOnce(&coFreeblInit, FreeblInit) != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ RSA_Init();
+
+ return SECSuccess;
+}
diff --git a/nss/lib/freebl/det_rng.c b/nss/lib/freebl/det_rng.c
index fcbf9b3..04fce30 100644
--- a/nss/lib/freebl/det_rng.c
+++ b/nss/lib/freebl/det_rng.c
@@ -9,10 +9,32 @@
#include "seccomon.h"
#include "secerr.h"
+#define GLOBAL_BYTES_SIZE 100
+static PRUint8 globalBytes[GLOBAL_BYTES_SIZE];
static unsigned long globalNumCalls = 0;
+static PZLock *rng_lock = NULL;
SECStatus
-prng_ResetForFuzzing(PZLock *rng_lock)
+RNG_RNGInit(void)
+{
+ rng_lock = PZ_NewLock(nssILockOther);
+ if (!rng_lock) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ /* --- LOCKED --- */
+ PZ_Lock(rng_lock);
+ memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
+ PZ_Unlock(rng_lock);
+ /* --- UNLOCKED --- */
+
+ return SECSuccess;
+}
+
+/* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset
+ * the rng state. */
+SECStatus
+RNG_RandomUpdate(const void *data, size_t bytes)
{
/* Check for a valid RNG lock. */
PORT_Assert(rng_lock != NULL);
@@ -23,7 +45,11 @@ prng_ResetForFuzzing(PZLock *rng_lock)
/* --- LOCKED --- */
PZ_Lock(rng_lock);
+ memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
globalNumCalls = 0;
+ if (data) {
+ memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE));
+ }
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
@@ -31,9 +57,9 @@ prng_ResetForFuzzing(PZLock *rng_lock)
}
SECStatus
-prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len)
+RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
{
- static const uint8_t key[32];
+ static const uint8_t key[32] = { 0 };
uint8_t nonce[12] = { 0 };
/* Check for a valid RNG lock. */
@@ -58,10 +84,60 @@ prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len)
}
memset(dest, 0, len);
+ memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE));
ChaCha20XOR(dest, dest, len, key, nonce, 0);
ChaCha20Poly1305_DestroyContext(cx, PR_TRUE);
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
+
return SECSuccess;
}
+
+void
+RNG_RNGShutdown(void)
+{
+ PZ_DestroyLock(rng_lock);
+ rng_lock = NULL;
+}
+
+/* Test functions are not implemented! */
+SECStatus
+PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *nonce, unsigned int nonce_len,
+ const PRUint8 *personal_string, unsigned int ps_len)
+{
+ return SECFailure;
+}
+
+SECStatus
+PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *additional, unsigned int additional_len)
+{
+ return SECFailure;
+}
+
+SECStatus
+PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
+ const PRUint8 *additional, unsigned int additional_len)
+{
+ return SECFailure;
+}
+
+SECStatus
+PRNGTEST_Uninstantiate()
+{
+ return SECFailure;
+}
+
+SECStatus
+PRNGTEST_RunHealthTests()
+{
+ return SECFailure;
+}
+
+SECStatus
+PRNGTEST_Instantiate_Kat()
+{
+ return SECFailure;
+}
diff --git a/nss/lib/freebl/dh.c b/nss/lib/freebl/dh.c
index 97025c7..587982a 100644
--- a/nss/lib/freebl/dh.c
+++ b/nss/lib/freebl/dh.c
@@ -14,9 +14,9 @@
#include "secerr.h"
#include "blapi.h"
+#include "blapii.h"
#include "secitem.h"
#include "mpi.h"
-#include "mpprime.h"
#include "secmpi.h"
#define KEA_DERIVED_SECRET_LEN 128
@@ -46,9 +46,7 @@ DH_GenParam(int primeLen, DHParams **params)
{
PLArenaPool *arena;
DHParams *dhparams;
- unsigned char *pb = NULL;
unsigned char *ab = NULL;
- unsigned long counter = 0;
mp_int p, q, a, h, psub1, test;
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
@@ -81,12 +79,7 @@ DH_GenParam(int primeLen, DHParams **params)
CHECK_MPI_OK(mp_init(&psub1));
CHECK_MPI_OK(mp_init(&test));
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
- pb = PORT_Alloc(primeLen);
- CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(pb, primeLen));
- pb[0] |= 0x80; /* set high-order bit */
- pb[primeLen - 1] |= 0x01; /* set low-order bit */
- CHECK_MPI_OK(mp_read_unsigned_octets(&p, pb, primeLen));
- CHECK_MPI_OK(mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter));
+ CHECK_SEC_OK(generate_prime(&p, primeLen));
/* construct Sophie-Germain prime q = (p-1)/2. */
CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1));
CHECK_MPI_OK(mp_div_2(&psub1, &q));
@@ -121,8 +114,6 @@ cleanup:
mp_clear(&h);
mp_clear(&psub1);
mp_clear(&test);
- if (pb)
- PORT_ZFree(pb, primeLen);
if (ab)
PORT_ZFree(ab, primeLen);
if (err) {
diff --git a/nss/lib/freebl/drbg.c b/nss/lib/freebl/drbg.c
index 658faa3..224bbe8 100644
--- a/nss/lib/freebl/drbg.c
+++ b/nss/lib/freebl/drbg.c
@@ -20,10 +20,6 @@
#include "secrng.h" /* for RNG_SystemRNG() */
#include "secmpi.h"
-#ifdef UNSAFE_FUZZER_MODE
-#include "det_rng.h"
-#endif
-
/* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1
* for SHA-1, SHA-224, and SHA-256 it's 440 bits.
* for SHA-384 and SHA-512 it's 888 bits */
@@ -99,7 +95,8 @@ struct RNGContextStr {
* RNG_RandomUpdate. */
PRUint8 additionalDataCache[PRNG_ADDITONAL_DATA_CACHE_SIZE];
PRUint32 additionalAvail;
- PRBool isValid; /* false if RNG reaches an invalid state */
+ PRBool isValid; /* false if RNG reaches an invalid state */
+ PRBool isKatTest; /* true if running NIST PRNG KAT tests */
};
typedef struct RNGContextStr RNGContext;
@@ -150,7 +147,7 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
}
/*
- * Hash_DRBG Instantiate NIST SP 800-80 10.1.1.2
+ * Hash_DRBG Instantiate NIST SP 800-90 10.1.1.2
*
* NOTE: bytes & len are entropy || nonce || personalization_string. In
* normal operation, NSS calculates them all together in a single call.
@@ -158,9 +155,11 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
static SECStatus
prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
{
- if (len < PRNG_SEEDLEN) {
- /* if the seedlen is to small, it's probably because we failed to get
- * enough random data */
+ if (!rng->isKatTest && len < PRNG_SEEDLEN) {
+ /* If the seedlen is too small, it's probably because we failed to get
+ * enough random data.
+ * This is stricter than NIST SP800-90A requires. Don't enforce it for
+ * tests. */
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
@@ -272,7 +271,7 @@ prng_reseed_test(RNGContext *rng, const PRUint8 *entropy,
#define PRNG_ADD_BITS_AND_CARRY(dest, dest_len, add, len, carry) \
PRNG_ADD_BITS(dest, dest_len, add, len, carry) \
- PRNG_ADD_CARRY_ONLY(dest, dest_len - len, carry)
+ PRNG_ADD_CARRY_ONLY(dest, dest_len - len - 1, carry)
/*
* This function expands the internal state of the prng to fulfill any number
@@ -435,12 +434,13 @@ rng_init(void)
globalrng = NULL;
return PR_FAILURE;
}
-
if (rv != SECSuccess) {
return PR_FAILURE;
}
+
/* the RNG is in a valid state */
globalrng->isValid = PR_TRUE;
+ globalrng->isKatTest = PR_FALSE;
/* fetch one random value so that we can populate rng->oldV for our
* continous random number test. */
@@ -654,21 +654,7 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng,
SECStatus
RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
{
-#ifdef UNSAFE_FUZZER_MODE
- return prng_GenerateDeterministicRandomBytes(globalrng->lock, dest, len);
-#else
return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
-#endif
-}
-
-SECStatus
-RNG_ResetForFuzzing(void)
-{
-#ifdef UNSAFE_FUZZER_MODE
- return prng_ResetForFuzzing(globalrng->lock);
-#else
- return SECFailure;
-#endif
}
void
@@ -696,6 +682,17 @@ RNG_RNGShutdown(void)
* entropy we may have previously collected. */
RNGContext testContext;
+SECStatus
+PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
+ const PRUint8 *nonce, unsigned int nonce_len,
+ const PRUint8 *personal_string, unsigned int ps_len)
+{
+ testContext.isKatTest = PR_TRUE;
+ return PRNGTEST_Instantiate(entropy, entropy_len,
+ nonce, nonce_len,
+ personal_string, ps_len);
+}
+
/*
* Test vector API. Use NIST SP 800-90 general interface so one of the
* other NIST SP 800-90 algorithms may be used in the future.
diff --git a/nss/lib/freebl/ec.c b/nss/lib/freebl/ec.c
index a9b7c05..669c9b1 100644
--- a/nss/lib/freebl/ec.c
+++ b/nss/lib/freebl/ec.c
@@ -233,7 +233,6 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
key->ecParams.type = ecParams->type;
key->ecParams.fieldID.size = ecParams->fieldID.size;
key->ecParams.fieldID.type = ecParams->fieldID.type;
- key->ecParams.pointSize = ecParams->pointSize;
if (ecParams->fieldID.type == ec_field_GFp ||
ecParams->fieldID.type == ec_field_plain) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
@@ -262,7 +261,7 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
&ecParams->curveOID));
- SECITEM_AllocItem(arena, &key->publicValue, ecParams->pointSize);
+ SECITEM_AllocItem(arena, &key->publicValue, EC_GetPointSize(ecParams));
len = ecParams->order.len;
SECITEM_AllocItem(arena, &key->privateValue, len);
@@ -566,11 +565,20 @@ ECDH_Derive(SECItem *publicValue,
return SECFailure;
}
+ /*
+ * Make sure the point is on the requested curve to avoid
+ * certain small subgroup attacks.
+ */
+ if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ return SECFailure;
+ }
+
/* Perform curve specific multiplication using ECMethod */
if (ecParams->fieldID.type == ec_field_plain) {
const ECMethod *method;
memset(derivedSecret, 0, sizeof(*derivedSecret));
- derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, ecParams->pointSize);
+ derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, EC_GetPointSize(ecParams));
if (derivedSecret == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
@@ -581,10 +589,6 @@ ECDH_Derive(SECItem *publicValue,
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
- if (method->validate(publicValue) != SECSuccess) {
- PORT_SetError(SEC_ERROR_BAD_KEY);
- return SECFailure;
- }
return method->mul(derivedSecret, privateValue, publicValue);
}
@@ -600,8 +604,8 @@ ECDH_Derive(SECItem *publicValue,
MP_DIGITS(&k) = 0;
memset(derivedSecret, 0, sizeof *derivedSecret);
len = (ecParams->fieldID.size + 7) >> 3;
- pointQ.len = ecParams->pointSize;
- if ((pointQ.data = PORT_Alloc(ecParams->pointSize)) == NULL)
+ pointQ.len = EC_GetPointSize(ecParams);
+ if ((pointQ.data = PORT_Alloc(pointQ.len)) == NULL)
goto cleanup;
CHECK_MPI_OK(mp_init(&k));
@@ -648,7 +652,7 @@ cleanup:
}
if (pointQ.data) {
- PORT_ZFree(pointQ.data, ecParams->pointSize);
+ PORT_ZFree(pointQ.data, pointQ.len);
}
#else
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
@@ -763,8 +767,8 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
**
** Compute kG
*/
- kGpoint.len = ecParams->pointSize;
- kGpoint.data = PORT_Alloc(ecParams->pointSize);
+ kGpoint.len = EC_GetPointSize(ecParams);
+ kGpoint.data = PORT_Alloc(kGpoint.len);
if ((kGpoint.data == NULL) ||
(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess))
goto cleanup;
@@ -883,7 +887,7 @@ cleanup:
}
if (kGpoint.data) {
- PORT_ZFree(kGpoint.data, ecParams->pointSize);
+ PORT_ZFree(kGpoint.data, kGpoint.len);
}
if (err) {
@@ -1002,9 +1006,14 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
}
slen = signature->len / 2;
- SECITEM_AllocItem(NULL, &pointC, ecParams->pointSize);
- if (pointC.data == NULL)
+ /*
+ * The incoming point has been verified in sftk_handlePublicKeyObject.
+ */
+
+ SECITEM_AllocItem(NULL, &pointC, EC_GetPointSize(ecParams));
+ if (pointC.data == NULL) {
goto cleanup;
+ }
CHECK_MPI_OK(mp_init(&r_));
CHECK_MPI_OK(mp_init(&s_));
diff --git a/nss/lib/freebl/ecdecode.c b/nss/lib/freebl/ecdecode.c
index eda3f0c..54b3e11 100644
--- a/nss/lib/freebl/ecdecode.c
+++ b/nss/lib/freebl/ecdecode.c
@@ -22,57 +22,6 @@
if (SECSuccess != (rv = func)) \
goto cleanup
-/*
- * Initializes a SECItem from a hexadecimal string
- *
- * Warning: This function ignores leading 00's, so any leading 00's
- * in the hexadecimal string must be optional.
- */
-static SECItem *
-hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
-{
- int i = 0;
- int byteval = 0;
- int tmp = PORT_Strlen(str);
-
- PORT_Assert(arena);
- PORT_Assert(item);
-
- if ((tmp % 2) != 0)
- return NULL;
-
- /* skip leading 00's unless the hex string is "00" */
- while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
- str += 2;
- tmp -= 2;
- }
-
- item->data = (unsigned char *)PORT_ArenaAlloc(arena, tmp / 2);
- if (item->data == NULL)
- return NULL;
- item->len = tmp / 2;
-
- while (str[i]) {
- if ((str[i] >= '0') && (str[i] <= '9'))
- tmp = str[i] - '0';
- else if ((str[i] >= 'a') && (str[i] <= 'f'))
- tmp = str[i] - 'a' + 10;
- else if ((str[i] >= 'A') && (str[i] <= 'F'))
- tmp = str[i] - 'A' + 10;
- else
- return NULL;
-
- byteval = byteval * 16 + tmp;
- if ((i % 2) != 0) {
- item->data[i / 2] = byteval;
- byteval = 0;
- }
- i++;
- }
-
- return item;
-}
-
/* Copy all of the fields from srcParams into dstParams
*/
SECStatus
@@ -85,7 +34,6 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
dstParams->type = srcParams->type;
dstParams->fieldID.size = srcParams->fieldID.size;
dstParams->fieldID.type = srcParams->fieldID.type;
- dstParams->pointSize = srcParams->pointSize;
if (srcParams->fieldID.type == ec_field_GFp ||
srcParams->fieldID.type == ec_field_plain) {
CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
@@ -121,12 +69,10 @@ cleanup:
}
static SECStatus
-gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
+gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params)
{
SECStatus rv = SECFailure;
- const ECCurveParams *curveParams;
- /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
- char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+ const ECCurveBytes *curveParams;
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
goto cleanup;
@@ -135,27 +81,19 @@ gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
CHECK_OK(curveParams);
params->fieldID.size = curveParams->size;
params->fieldID.type = field_type;
- params->pointSize = curveParams->pointSize;
- if (field_type == ec_field_GFp ||
- field_type == ec_field_plain) {
- CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
- curveParams->irr));
- } else {
- CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly,
- curveParams->irr));
+ if (field_type != ec_field_GFp && field_type != ec_field_plain) {
+ return SECFailure;
}
- CHECK_OK(hexString2SECItem(params->arena, &params->curve.a,
- curveParams->curvea));
- CHECK_OK(hexString2SECItem(params->arena, &params->curve.b,
- curveParams->curveb));
- genenc[0] = '0';
- genenc[1] = '4';
- genenc[2] = '\0';
- strcat(genenc, curveParams->genx);
- strcat(genenc, curveParams->geny);
- CHECK_OK(hexString2SECItem(params->arena, &params->base, genenc));
- CHECK_OK(hexString2SECItem(params->arena, &params->order,
- curveParams->order));
+ params->fieldID.u.prime.len = curveParams->scalarSize;
+ params->fieldID.u.prime.data = (unsigned char *)curveParams->irr;
+ params->curve.a.len = curveParams->scalarSize;
+ params->curve.a.data = (unsigned char *)curveParams->curvea;
+ params->curve.b.len = curveParams->scalarSize;
+ params->curve.b.data = (unsigned char *)curveParams->curveb;
+ params->base.len = curveParams->pointSize;
+ params->base.data = (unsigned char *)curveParams->base;
+ params->order.len = curveParams->scalarSize;
+ params->order.data = (unsigned char *)curveParams->order;
params->cofactor = curveParams->cofactor;
rv = SECSuccess;
@@ -218,29 +156,30 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
/* Populate params for prime256v1 aka secp256r1
* (the NIST P-256 curve)
*/
- CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
- params));
+ CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_X9_62_PRIME_256V1,
+ ec_field_GFp, params));
break;
case SEC_OID_SECG_EC_SECP384R1:
/* Populate params for secp384r1
* (the NIST P-384 curve)
*/
- CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
- params));
+ CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1,
+ ec_field_GFp, params));
break;
case SEC_OID_SECG_EC_SECP521R1:
/* Populate params for secp521r1
* (the NIST P-521 curve)
*/
- CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
- params));
+ CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
+ ec_field_GFp, params));
break;
case SEC_OID_CURVE25519:
/* Populate params for Curve25519 */
- CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
+ CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519, ec_field_plain,
+ params));
break;
default:
@@ -294,4 +233,24 @@ EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams)
}
}
+int
+EC_GetPointSize(const ECParams *params)
+{
+ ECCurveName name = params->name;
+ const ECCurveBytes *curveParams;
+
+ if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
+ ((curveParams = ecCurve_map[name]) == NULL)) {
+ /* unknown curve, calculate point size from params. assume standard curves with 2 points
+ * and a point compression indicator byte */
+ int sizeInBytes = (params->fieldID.size + 7) / 8;
+ return sizeInBytes * 2 + 1;
+ }
+ if (name == ECCurve25519) {
+ /* Only X here */
+ return curveParams->scalarSize;
+ }
+ return curveParams->pointSize - 1;
+}
+
#endif /* NSS_DISABLE_ECC */
diff --git a/nss/lib/freebl/ecl/README b/nss/lib/freebl/ecl/README
index 04a8b3b..2996822 100644
--- a/nss/lib/freebl/ecl/README
+++ b/nss/lib/freebl/ecl/README
@@ -90,20 +90,6 @@ the linear coefficient in the curve defining equation).
ecp_192.c and ecp_224.c provide optimized field arithmetic.
-Point Arithmetic over Binary Polynomial Fields
-----------------------------------------------
-
-ec2_aff.c provides point arithmetic using affine coordinates.
-
-ec2_proj.c provides point arithmetic using projective coordinates.
-(Projective coordinates represent a point (x, y) as (X, Y, Z), where
-x=X/Z, y=Y/Z^2).
-
-ec2_mont.c provides point multiplication using Montgomery projective
-coordinates.
-
-ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
-
Field Arithmetic
----------------
@@ -126,18 +112,6 @@ fields defined by nistp192 and nistp224 primes.
ecl_gf.c provides wrappers around the basic field operations.
-Binary Polynomial Field Arithmetic
-----------------------------------
-
-../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
-including addition, multiplication, squaring, mod, and division, as well
-as conversion ob polynomial representations between bitstring and int[].
-
-ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
-and sqr operations.
-
-ecl_gf.c provides wrappers around the basic field operations.
-
Field Encoding
--------------
@@ -187,81 +161,3 @@ arithmetic. Instead, they use basic field arithmetic with their
optimized reduction (as in ecp_192.c and ecp_224.c). They
use the same point multiplication and simultaneous point multiplication
algorithms as other curves over prime fields.
-
-Curves over binary polynomial fields by default use generic field
-arithmetic with montgomery point multiplication and basic kP + lQ
-computation (multiply, multiply, and add). (Wiring in function
-ECGroup_cons_GF2m in ecl.c.)
-
-Curves over binary polynomial fields that have optimized field
-arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
-field arithmetic. They use the same point multiplication and
-simultaneous point multiplication algorithms as other curves over binary
-fields.
-
-Example
--------
-
-We provide an example for plugging in an optimized implementation for
-the Koblitz curve nistk163.
-
-Suppose the file ec2_k163.c contains the optimized implementation. In
-particular it contains a point multiplication function:
-
- mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
- const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
-
-Since only a pt_mul function is provided, the generic pt_add function
-will be used.
-
-There are two options for handling the optimized field arithmetic used
-by the ..._pt_mul function. Say the optimized field arithmetic includes
-the following functions:
-
- mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
- mp_int *r, const GFMethod *meth);
- mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
- mp_int *r, const GFMethod *meth);
- mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
- mp_int *r, const GFMethod *meth);
- mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
- mp_int *r, const GFMethod *meth);
-
-First, the optimized field arithmetic could simply be called directly
-by the ..._pt_mul function. This would be accomplished by changing
-the ecgroup_fromNameAndHex function in ecl.c to include the following
-statements:
-
- if (name == ECCurve_NIST_K163) {
- group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
- &geny, &order, params->cofactor);
- if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
- MP_CHECKOK( ec_group_set_nistk163(group) );
- }
-
-and including in ec2_k163.c the following function:
-
- mp_err ec_group_set_nistk163(ECGroup *group) {
- group->point_mul = &ec_GF2m_nistk163_pt_mul;
- return MP_OKAY;
- }
-
-As a result, ec_GF2m_pt_add and similar functions would use the
-basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
-ec_GF2m_sqr, and ec_GF2m_div.
-
-Alternatively, the optimized field arithmetic could be wired into the
-group's GFMethod. This would be accomplished by putting the following
-function in ec2_k163.c:
-
- mp_err ec_group_set_nistk163(ECGroup *group) {
- group->meth->field_add = &ec_GF2m_nistk163_add;
- group->meth->field_mul = &ec_GF2m_nistk163_mul;
- group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
- group->meth->field_div = &ec_GF2m_nistk163_div;
- group->point_mul = &ec_GF2m_nistk163_pt_mul;
- return MP_OKAY;
- }
-
-For an example of functions that use special field encodings, take a
-look at ecp_mont.c.
diff --git a/nss/lib/freebl/ecl/curve25519_64.c b/nss/lib/freebl/ecl/curve25519_64.c
index 89327ad..65f6bd4 100644
--- a/nss/lib/freebl/ecl/curve25519_64.c
+++ b/nss/lib/freebl/ecl/curve25519_64.c
@@ -206,7 +206,7 @@ fexpand(felem *output, const u8 *in)
output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
- output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51;
+ output[4] = (*((const uint64_t *)(in + 24)) >> 12) & MASK51;
}
/* Take a fully reduced polynomial form number and contract it into a
diff --git a/nss/lib/freebl/ecl/ecl-curve.h b/nss/lib/freebl/ecl/ecl-curve.h
index df06139..fc8003f 100644
--- a/nss/lib/freebl/ecl/ecl-curve.h
+++ b/nss/lib/freebl/ecl/ecl-curve.h
@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecl-exp.h"
+#include "eclt.h"
#include <stdlib.h>
#ifndef __ecl_curve_h_
@@ -12,52 +13,201 @@
#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
-static const ECCurveParams ecCurve_NIST_P256 = {
+static const PRUint8 irr256[32] =
+ { 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const PRUint8 a256[32] =
+ { 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
+static const PRUint8 b256[32] =
+ { 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
+ 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
+ 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
+static const PRUint8 x256[32] =
+ { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
+static const PRUint8 y256[32] =
+ { 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
+ 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
+ 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
+static const PRUint8 order256[32] =
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
+static const PRUint8 base256[66] =
+ { 0x04, 0x00,
+ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
+ 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
+ 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
+ 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
+
+static const ECCurveBytes ecCurve_NIST_P256 = {
"NIST-P256", ECField_GFp, 256,
- "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
- "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
- "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
- "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
- "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
- 1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+ irr256, a256, b256, x256, y256, order256, base256,
+ 1, 128, 66, 32,
+ KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
-static const ECCurveParams ecCurve_NIST_P384 = {
+static const PRUint8 irr384[48] =
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
+static const PRUint8 a384[48] =
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
+static const PRUint8 b384[48] =
+ { 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
+ 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
+ 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
+ 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
+static const PRUint8 x384[48] =
+ { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+ 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+ 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+ 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
+static const PRUint8 y384[48] =
+ { 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
+ 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
+ 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
+ 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
+static const PRUint8 order384[48] =
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
+ 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
+static const PRUint8 base384[98] =
+ { 0x04, 0x00,
+ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+ 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+ 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+ 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
+ 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
+ 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
+ 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
+ 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
+
+static const ECCurveBytes ecCurve_NIST_P384 = {
"NIST-P384", ECField_GFp, 384,
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
- "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
- "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
- "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- 1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+ irr384, a384, b384, x384, y384, order384, base384,
+ 1, 192, 98, 48,
+ KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
-static const ECCurveParams ecCurve_NIST_P521 = {
+static const PRUint8 irr521[66] =
+ { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+static const PRUint8 a521[66] =
+ { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
+static const PRUint8 b521[66] =
+ { 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
+ 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
+ 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
+ 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
+ 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
+ 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
+static const PRUint8 x521[66] =
+ { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+ 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+ 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+ 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+ 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+ 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
+static const PRUint8 y521[66] =
+ { 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
+ 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
+ 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
+ 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
+ 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
+ 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
+static const PRUint8 order521[66] =
+ { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
+ 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+ 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
+ 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
+static const PRUint8 base521[134] =
+ {
+ 0x04, 0x00,
+ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+ 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+ 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+ 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+ 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+ 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
+ 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
+ 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
+ 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
+ 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
+ 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
+ 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
+ };
+
+static const ECCurveBytes ecCurve_NIST_P521 = {
"NIST-P521", ECField_GFp, 521,
- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
- "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
- "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
- "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
- "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- 1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
+ irr521, a521, b521, x521, y521, order521, base521,
+ 1, 256, 134, 66,
+ KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
-static const ECCurveParams ecCurve25519 = {
+static const PRUint8 irr25519[32] =
+ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
+static const PRUint8 a25519[32] =
+ { 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const PRUint8 b25519[32] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const PRUint8 x25519[32] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
+static const PRUint8 y25519[32] =
+ { 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
+ 0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
+ 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
+static const PRUint8 order25519[32] =
+ { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
+ 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
+static const PRUint8 base25519[66] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
+ 0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
+ 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
+
+static const ECCurveBytes ecCurve_25519 = {
"Curve25519", ECField_GFp, 255,
- "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
- "076D06",
- "00",
- "0900000000000000000000000000000000000000000000000000000000000000",
- "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
- "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
- 8, 128, 32, KU_KEY_AGREEMENT
+ irr25519, a25519, b25519, x25519, y25519, order25519, base25519,
+ 8, 128, 66, 32,
+ KU_KEY_AGREEMENT
};
/* mapping between ECCurveName enum and pointers to ECCurveParams */
-static const ECCurveParams *ecCurve_map[] = {
+static const ECCurveBytes *ecCurve_map[] = {
NULL, /* ECCurve_noName */
NULL, /* ECCurve_NIST_P192 */
NULL, /* ECCurve_NIST_P224 */
@@ -116,7 +266,7 @@ static const ECCurveParams *ecCurve_map[] = {
NULL, /* ECCurve_WTLS_1 */
NULL, /* ECCurve_WTLS_8 */
NULL, /* ECCurve_WTLS_9 */
- &ecCurve25519, /* ECCurve25519 */
+ &ecCurve_25519, /* ECCurve25519 */
NULL /* ECCurve_pastLastCurve */
};
diff --git a/nss/lib/freebl/ecl/ecl-priv.h b/nss/lib/freebl/ecl/ecl-priv.h
index f43f193..2168559 100644
--- a/nss/lib/freebl/ecl/ecl-priv.h
+++ b/nss/lib/freebl/ecl/ecl-priv.h
@@ -246,12 +246,5 @@ mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
/* Optimized point multiplication */
mp_err ec_group_set_gfp256_32(ECGroup *group, ECCurveName name);
-/* Optimized floating-point arithmetic */
-#ifdef ECL_USE_FP
-mp_err ec_group_set_secp160r1_fp(ECGroup *group);
-mp_err ec_group_set_nistp192_fp(ECGroup *group);
-mp_err ec_group_set_nistp224_fp(ECGroup *group);
-#endif
-
SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
#endif /* __ecl_priv_h_ */
diff --git a/nss/lib/freebl/ecl/ecl.c b/nss/lib/freebl/ecl/ecl.c
index 3540af7..ca87b49 100644
--- a/nss/lib/freebl/ecl/ecl.c
+++ b/nss/lib/freebl/ecl/ecl.c
@@ -2,11 +2,16 @@
* 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 "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecl-priv.h"
#include "ecp.h"
+#include "ecl-curve.h"
#include <stdlib.h>
#include <string.h>
@@ -128,37 +133,16 @@ CLEANUP:
return group;
}
-/* Construct ECGroup from hex parameters and name, if any. Called by
- * ECGroup_fromHex and ECGroup_fromName. */
+/* Construct an ECGroup. */
ECGroup *
-ecgroup_fromNameAndHex(const ECCurveName name,
- const ECCurveParams *params)
+construct_ecgroup(const ECCurveName name, mp_int irr, mp_int curvea,
+ mp_int curveb, mp_int genx, mp_int geny, mp_int order,
+ int cofactor, ECField field, const char *text)
{
- mp_int irr, curvea, curveb, genx, geny, order;
int bits;
ECGroup *group = NULL;
mp_err res = MP_OKAY;
- /* initialize values */
- MP_DIGITS(&irr) = 0;
- MP_DIGITS(&curvea) = 0;
- MP_DIGITS(&curveb) = 0;
- MP_DIGITS(&genx) = 0;
- MP_DIGITS(&geny) = 0;
- MP_DIGITS(&order) = 0;
- MP_CHECKOK(mp_init(&irr));
- MP_CHECKOK(mp_init(&curvea));
- MP_CHECKOK(mp_init(&curveb));
- MP_CHECKOK(mp_init(&genx));
- MP_CHECKOK(mp_init(&geny));
- MP_CHECKOK(mp_init(&order));
- MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
- MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
- MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
- MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
- MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
- MP_CHECKOK(mp_read_radix(&order, params->order, 16));
-
/* determine number of bits */
bits = mpl_significant_bits(&irr) - 1;
if (bits < MP_OKAY) {
@@ -167,12 +151,12 @@ ecgroup_fromNameAndHex(const ECCurveName name,
}
/* determine which optimizations (if any) to use */
- if (params->field == ECField_GFp) {
+ if (field == ECField_GFp) {
switch (name) {
case ECCurve_SECG_PRIME_256R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
- &order, params->cofactor);
+ &order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
@@ -183,7 +167,7 @@ ecgroup_fromNameAndHex(const ECCurveName name,
case ECCurve_SECG_PRIME_521R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
- &order, params->cofactor);
+ &order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
@@ -194,7 +178,7 @@ ecgroup_fromNameAndHex(const ECCurveName name,
/* use generic arithmetic */
group =
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
- &order, params->cofactor);
+ &order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
@@ -206,62 +190,95 @@ ecgroup_fromNameAndHex(const ECCurveName name,
}
/* set name, if any */
- if ((group != NULL) && (params->text != NULL)) {
- group->text = strdup(params->text);
+ if ((group != NULL) && (text != NULL)) {
+ group->text = strdup(text);
if (group->text == NULL) {
res = MP_MEM;
}
}
CLEANUP:
+ if (group && res != MP_OKAY) {
+ ECGroup_free(group);
+ return NULL;
+ }
+ return group;
+}
+
+/* Construct ECGroup from parameters and name, if any. */
+ECGroup *
+ecgroup_fromName(const ECCurveName name,
+ const ECCurveBytes *params)
+{
+ mp_int irr, curvea, curveb, genx, geny, order;
+ ECGroup *group = NULL;
+ mp_err res = MP_OKAY;
+
+ /* initialize values */
+ MP_DIGITS(&irr) = 0;
+ MP_DIGITS(&curvea) = 0;
+ MP_DIGITS(&curveb) = 0;
+ MP_DIGITS(&genx) = 0;
+ MP_DIGITS(&geny) = 0;
+ MP_DIGITS(&order) = 0;
+ MP_CHECKOK(mp_init(&irr));
+ MP_CHECKOK(mp_init(&curvea));
+ MP_CHECKOK(mp_init(&curveb));
+ MP_CHECKOK(mp_init(&genx));
+ MP_CHECKOK(mp_init(&geny));
+ MP_CHECKOK(mp_init(&order));
+ MP_CHECKOK(mp_read_unsigned_octets(&irr, params->irr, params->scalarSize));
+ MP_CHECKOK(mp_read_unsigned_octets(&curvea, params->curvea, params->scalarSize));
+ MP_CHECKOK(mp_read_unsigned_octets(&curveb, params->curveb, params->scalarSize));
+ MP_CHECKOK(mp_read_unsigned_octets(&genx, params->genx, params->scalarSize));
+ MP_CHECKOK(mp_read_unsigned_octets(&geny, params->geny, params->scalarSize));
+ MP_CHECKOK(mp_read_unsigned_octets(&order, params->order, params->scalarSize));
+
+ group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
+ params->cofactor, params->field, params->text);
+
+CLEANUP:
mp_clear(&irr);
mp_clear(&curvea);
mp_clear(&curveb);
mp_clear(&genx);
mp_clear(&geny);
mp_clear(&order);
- if (res != MP_OKAY) {
+ if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
-/* Construct ECGroup from hexadecimal representations of parameters. */
-ECGroup *
-ECGroup_fromHex(const ECCurveParams *params)
+/* Construct ECCurveBytes from an ECCurveName */
+const ECCurveBytes *
+ec_GetNamedCurveParams(const ECCurveName name)
{
- return ecgroup_fromNameAndHex(ECCurve_noName, params);
+ if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
+ (ecCurve_map[name] == NULL)) {
+ return NULL;
+ } else {
+ return ecCurve_map[name];
+ }
}
/* Construct ECGroup from named parameters. */
ECGroup *
ECGroup_fromName(const ECCurveName name)
{
- ECGroup *group = NULL;
- ECCurveParams *params = NULL;
- mp_err res = MP_OKAY;
+ const ECCurveBytes *params = NULL;
- params = EC_GetNamedCurveParams(name);
+ /* This doesn't work with Curve25519 but it's not necessary to. */
+ PORT_Assert(name != ECCurve25519);
+
+ params = ec_GetNamedCurveParams(name);
if (params == NULL) {
- res = MP_UNDEF;
- goto CLEANUP;
+ return NULL;
}
/* construct actual group */
- group = ecgroup_fromNameAndHex(name, params);
- if (group == NULL) {
- res = MP_UNDEF;
- goto CLEANUP;
- }
-
-CLEANUP:
- EC_FreeCurveParams(params);
- if (res != MP_OKAY) {
- ECGroup_free(group);
- return NULL;
- }
- return group;
+ return ecgroup_fromName(name, params);
}
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
diff --git a/nss/lib/freebl/ecl/ecl.h b/nss/lib/freebl/ecl/ecl.h
index ddcbb1f..f6d5bc4 100644
--- a/nss/lib/freebl/ecl/ecl.h
+++ b/nss/lib/freebl/ecl/ecl.h
@@ -11,28 +11,17 @@
#include "blapi.h"
#include "ecl-exp.h"
#include "mpi.h"
+#include "eclt.h"
struct ECGroupStr;
typedef struct ECGroupStr ECGroup;
-/* Construct ECGroup from hexadecimal representations of parameters. */
-ECGroup *ECGroup_fromHex(const ECCurveParams *params);
-
/* Construct ECGroup from named parameters. */
ECGroup *ECGroup_fromName(const ECCurveName name);
/* Free an allocated ECGroup. */
void ECGroup_free(ECGroup *group);
-/* Construct ECCurveParams from an ECCurveName */
-ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
-
-/* Duplicates an ECCurveParams */
-ECCurveParams *ECCurveParams_dup(const ECCurveParams *params);
-
-/* Free an allocated ECCurveParams */
-void EC_FreeCurveParams(ECCurveParams *params);
-
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
* y). If x, y = NULL, then P is assumed to be the generator (base point)
* of the group of points on the elliptic curve. Input and output values
diff --git a/nss/lib/freebl/ecl/ecl_curve.c b/nss/lib/freebl/ecl/ecl_curve.c
deleted file mode 100644
index cf090cf..0000000
--- a/nss/lib/freebl/ecl/ecl_curve.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* 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/. */
-
-#include "ecl.h"
-#include "ecl-curve.h"
-#include "ecl-priv.h"
-#include <stdlib.h>
-#include <string.h>
-
-#define CHECK(func) \
- if ((func) == NULL) { \
- res = 0; \
- goto CLEANUP; \
- }
-
-/* Duplicates an ECCurveParams */
-ECCurveParams *
-ECCurveParams_dup(const ECCurveParams *params)
-{
- int res = 1;
- ECCurveParams *ret = NULL;
-
- CHECK(ret = (ECCurveParams *)calloc(1, sizeof(ECCurveParams)));
- if (params->text != NULL) {
- CHECK(ret->text = strdup(params->text));
- }
- ret->field = params->field;
- ret->size = params->size;
- if (params->irr != NULL) {
- CHECK(ret->irr = strdup(params->irr));
- }
- if (params->curvea != NULL) {
- CHECK(ret->curvea = strdup(params->curvea));
- }
- if (params->curveb != NULL) {
- CHECK(ret->curveb = strdup(params->curveb));
- }
- if (params->genx != NULL) {
- CHECK(ret->genx = strdup(params->genx));
- }
- if (params->geny != NULL) {
- CHECK(ret->geny = strdup(params->geny));
- }
- if (params->order != NULL) {
- CHECK(ret->order = strdup(params->order));
- }
- ret->cofactor = params->cofactor;
-
-CLEANUP:
- if (res != 1) {
- EC_FreeCurveParams(ret);
- return NULL;
- }
- return ret;
-}
-
-#undef CHECK
-
-/* Construct ECCurveParams from an ECCurveName */
-ECCurveParams *
-EC_GetNamedCurveParams(const ECCurveName name)
-{
- if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
- (ecCurve_map[name] == NULL)) {
- return NULL;
- } else {
- return ECCurveParams_dup(ecCurve_map[name]);
- }
-}
-
-/* Free the memory allocated (if any) to an ECCurveParams object. */
-void
-EC_FreeCurveParams(ECCurveParams *params)
-{
- if (params == NULL)
- return;
- if (params->text != NULL)
- free(params->text);
- if (params->irr != NULL)
- free(params->irr);
- if (params->curvea != NULL)
- free(params->curvea);
- if (params->curveb != NULL)
- free(params->curveb);
- if (params->genx != NULL)
- free(params->genx);
- if (params->geny != NULL)
- free(params->geny);
- if (params->order != NULL)
- free(params->order);
- free(params);
-}
diff --git a/nss/lib/freebl/ecl/eclt.h b/nss/lib/freebl/ecl/eclt.h
new file mode 100644
index 0000000..e763706
--- /dev/null
+++ b/nss/lib/freebl/ecl/eclt.h
@@ -0,0 +1,30 @@
+/* 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/. */
+
+/* This header holds ECC types and must not be exported publicly. */
+
+#ifndef __eclt_h_
+#define __eclt_h_
+
+/* byte encoding of curve parameters */
+struct ECCurveBytesStr {
+ char *text;
+ ECField field;
+ size_t size;
+ const PRUint8 *irr;
+ const PRUint8 *curvea;
+ const PRUint8 *curveb;
+ const PRUint8 *genx;
+ const PRUint8 *geny;
+ const PRUint8 *order;
+ const PRUint8 *base;
+ int cofactor;
+ int security;
+ size_t pointSize;
+ size_t scalarSize;
+ unsigned int usage;
+};
+typedef struct ECCurveBytesStr ECCurveBytes;
+
+#endif /* __ecl_h_ */
diff --git a/nss/lib/freebl/ecl/ecp_25519.c b/nss/lib/freebl/ecl/ecp_25519.c
index a8d4152..1e7875f 100644
--- a/nss/lib/freebl/ecl/ecp_25519.c
+++ b/nss/lib/freebl/ecl/ecp_25519.c
@@ -79,8 +79,7 @@ ec_Curve25519_pt_validate(const SECItem *px)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
};
- /* The point must not be longer than 32 (it can be smaller). */
- if (px->len <= 32) {
+ if (px->len == 32) {
p = px->data;
} else {
return SECFailure;
diff --git a/nss/lib/freebl/ecl/ecp_jm.c b/nss/lib/freebl/ecl/ecp_jm.c
index a1106ce..bd13fa0 100644
--- a/nss/lib/freebl/ecl/ecp_jm.c
+++ b/nss/lib/freebl/ecl/ecp_jm.c
@@ -127,6 +127,17 @@ ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
+ /* Check P == Q */
+ if (mp_cmp(A, px) == 0) {
+ if (mp_cmp(B, py) == 0) {
+ /* If Px == Qx && Py == Qy, double P. */
+ return ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
+ scratch, group);
+ }
+ /* If Px == Qx && Py != Qy, return point at infinity. */
+ return ec_GFp_pt_set_inf_jac(rx, ry, rz);
+ }
+
/* C = A - px, D = B - py */
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
diff --git a/nss/lib/freebl/ecl/tests/ec_naft.c b/nss/lib/freebl/ecl/tests/ec_naft.c
deleted file mode 100644
index 61ef15c..0000000
--- a/nss/lib/freebl/ecl/tests/ec_naft.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* 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/. */
-
-#include "mpi.h"
-#include "mplogic.h"
-#include "ecl.h"
-#include "ecp.h"
-#include "ecl-priv.h"
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-/* Returns 2^e as an integer. This is meant to be used for small powers of
- * two. */
-int ec_twoTo(int e);
-
-/* Number of bits of scalar to test */
-#define BITSIZE 160
-
-/* Time k repetitions of operation op. */
-#define M_TimeOperation(op, k) \
- { \
- double dStart, dNow, dUserTime; \
- struct rusage ru; \
- int i; \
- getrusage(RUSAGE_SELF, &ru); \
- dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
- for (i = 0; i < k; i++) { \
- { \
- op; \
- } \
- }; \
- getrusage(RUSAGE_SELF, &ru); \
- dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
- dUserTime = dNow - dStart; \
- if (dUserTime) \
- printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
- }
-
-/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D.
- * Hankerson, J. Hernandez and A. Menezes, "Software implementation of
- * elliptic curve cryptography over binary fields", Proc. CHES 2000. */
-
-mp_err
-main(void)
-{
- signed char naf[BITSIZE + 1];
- ECGroup *group = NULL;
- mp_int k;
- mp_int *scalar;
- int i, count;
- int res;
- int w = 5;
- char s[1000];
-
- /* Get a 160 bit scalar to compute wNAF from */
- group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
- scalar = &group->genx;
-
- /* Compute wNAF representation of scalar */
- ec_compute_wNAF(naf, BITSIZE, scalar, w);
-
- /* Verify correctness of representation */
- mp_init(&k); /* init k to 0 */
-
- for (i = BITSIZE; i >= 0; i--) {
- mp_add(&k, &k, &k);
- /* digits in mp_???_d are unsigned */
- if (naf[i] >= 0) {
- mp_add_d(&k, naf[i], &k);
- } else {
- mp_sub_d(&k, -naf[i], &k);
- }
- }
-
- if (mp_cmp(&k, scalar) != 0) {
- printf("Error: incorrect NAF value.\n");
- MP_CHECKOK(mp_toradix(&k, s, 16));
- printf("NAF value %s\n", s);
- MP_CHECKOK(mp_toradix(scalar, s, 16));
- printf("original value %s\n", s);
- goto CLEANUP;
- }
-
- /* Verify digits of representation are valid */
- for (i = 0; i <= BITSIZE; i++) {
- if (naf[i] % 2 == 0 && naf[i] != 0) {
- printf("Error: Even non-zero digit found.\n");
- goto CLEANUP;
- }
- if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
- printf("Error: Magnitude of naf digit too large.\n");
- goto CLEANUP;
- }
- }
-
- /* Verify sparsity of representation */
- count = w - 1;
- for (i = 0; i <= BITSIZE; i++) {
- if (naf[i] != 0) {
- if (count < w - 1) {
- printf("Error: Sparsity failed.\n");
- goto CLEANUP;
- }
- count = 0;
- } else
- count++;
- }
-
- /* Check timing */
- M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
-
- printf("Test passed.\n");
-CLEANUP:
- ECGroup_free(group);
- return MP_OKAY;
-}
diff --git a/nss/lib/freebl/ecl/tests/ecp_test.c b/nss/lib/freebl/ecl/tests/ecp_test.c
deleted file mode 100644
index dcec4d7..0000000
--- a/nss/lib/freebl/ecl/tests/ecp_test.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/* 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/. */
-
-#include "mpi.h"
-#include "mplogic.h"
-#include "mpprime.h"
-#include "ecl.h"
-#include "ecl-curve.h"
-#include "ecp.h"
-#include <stdio.h>
-#include <strings.h>
-#include <assert.h>
-
-#include <time.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-/* Time k repetitions of operation op. */
-#define M_TimeOperation(op, k) \
- { \
- double dStart, dNow, dUserTime; \
- struct rusage ru; \
- int i; \
- getrusage(RUSAGE_SELF, &ru); \
- dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
- for (i = 0; i < k; i++) { \
- { \
- op; \
- } \
- }; \
- getrusage(RUSAGE_SELF, &ru); \
- dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
- dUserTime = dNow - dStart; \
- if (dUserTime) \
- printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
- }
-
-/* Test curve using generic field arithmetic. */
-#define ECTEST_GENERIC_GFP(name_c, name) \
- printf("Testing %s using generic implementation...\n", name_c); \
- params = EC_GetNamedCurveParams(name); \
- if (params == NULL) { \
- printf(" Error: could not construct params.\n"); \
- res = MP_NO; \
- goto CLEANUP; \
- } \
- ECGroup_free(group); \
- group = ECGroup_fromHex(params); \
- if (group == NULL) { \
- printf(" Error: could not construct group.\n"); \
- res = MP_NO; \
- goto CLEANUP; \
- } \
- MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 1)); \
- printf("... okay.\n");
-
-/* Test curve using specific field arithmetic. */
-#define ECTEST_NAMED_GFP(name_c, name) \
- printf("Testing %s using specific implementation...\n", name_c); \
- ECGroup_free(group); \
- group = ECGroup_fromName(name); \
- if (group == NULL) { \
- printf(" Warning: could not construct group.\n"); \
- printf("... failed; continuing with remaining tests.\n"); \
- } else { \
- MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 0)); \
- printf("... okay.\n"); \
- }
-
-/* Performs basic tests of elliptic curve cryptography over prime fields.
- * If tests fail, then it prints an error message, aborts, and returns an
- * error code. Otherwise, returns 0. */
-int
-ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
- int generic)
-{
-
- mp_int one, order_1, gx, gy, rx, ry, n;
- int size;
- mp_err res;
- char s[1000];
-
- /* initialize values */
- MP_CHECKOK(mp_init(&one));
- MP_CHECKOK(mp_init(&order_1));
- MP_CHECKOK(mp_init(&gx));
- MP_CHECKOK(mp_init(&gy));
- MP_CHECKOK(mp_init(&rx));
- MP_CHECKOK(mp_init(&ry));
- MP_CHECKOK(mp_init(&n));
-
- MP_CHECKOK(mp_set_int(&one, 1));
- MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
-
- /* encode base point */
- if (group->meth->field_dec) {
- MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
- MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
- } else {
- MP_CHECKOK(mp_copy(&group->genx, &gx));
- MP_CHECKOK(mp_copy(&group->geny, &gy));
- }
- if (ectestPrint) {
- /* output base point */
- printf(" base point P:\n");
- MP_CHECKOK(mp_toradix(&gx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&gy, s, 16));
- printf(" %s\n", s);
- if (group->meth->field_enc) {
- printf(" base point P (encoded):\n");
- MP_CHECKOK(mp_toradix(&group->genx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&group->geny, s, 16));
- printf(" %s\n", s);
- }
- }
-
-#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
- /* multiply base point by order - 1 and check for negative of base
- * point */
- MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
- if (ectestPrint) {
- printf(" (order-1)*P (affine):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
- if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
- printf(" Error: invalid result (expected (- base point)).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-#endif
-
-#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
- /* multiply base point by order - 1 and check for negative of base
- * point */
- MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
- if (ectestPrint) {
- printf(" (order-1)*P (jacobian):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
- if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
- printf(" Error: invalid result (expected (- base point)).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-#endif
-
- /* multiply base point by order - 1 and check for negative of base
- * point */
- MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
- if (ectestPrint) {
- printf(" (order-1)*P (ECPoint_mul):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
- if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
- printf(" Error: invalid result (expected (- base point)).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
- /* multiply base point by order - 1 and check for negative of base
- * point */
- MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
- if (ectestPrint) {
- printf(" (order-1)*P (ECPoint_mul):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
- if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
- printf(" Error: invalid result (expected (- base point)).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
-#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
- /* multiply base point by order and check for point at infinity */
- MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
- group));
- if (ectestPrint) {
- printf(" (order)*P (affine):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
- printf(" Error: invalid result (expected point at infinity).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-#endif
-
-#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
- /* multiply base point by order and check for point at infinity */
- MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
- group));
- if (ectestPrint) {
- printf(" (order)*P (jacobian):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
- printf(" Error: invalid result (expected point at infinity).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-#endif
-
- /* multiply base point by order and check for point at infinity */
- MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
- if (ectestPrint) {
- printf(" (order)*P (ECPoint_mul):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
- printf(" Error: invalid result (expected point at infinity).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
- /* multiply base point by order and check for point at infinity */
- MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
- if (ectestPrint) {
- printf(" (order)*P (ECPoint_mul):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
- printf(" Error: invalid result (expected point at infinity).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
- /* check that (order-1)P + (order-1)P + P == (order-1)P */
- MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
- MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
- if (ectestPrint) {
- printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
- MP_CHECKOK(mp_toradix(&rx, s, 16));
- printf(" %s\n", s);
- MP_CHECKOK(mp_toradix(&ry, s, 16));
- printf(" %s\n", s);
- }
- MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
- if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
- printf(" Error: invalid result (expected (- base point)).\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
- /* test validate_point function */
- if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
- printf(" Error: validate point on base point failed.\n");
- res = MP_NO;
- goto CLEANUP;
- }
- MP_CHECKOK(mp_add_d(&gy, 1, &ry));
- if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
- printf(" Error: validate point on invalid point passed.\n");
- res = MP_NO;
- goto CLEANUP;
- }
-
- if (ectestTime) {
- /* compute random scalar */
- size = mpl_significant_bits(&group->meth->irr);
- if (size < MP_OKAY) {
- goto CLEANUP;
- }
- MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
- MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
- /* timed test */
- if (generic) {
-#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
- M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
- group)),
- 100);
-#endif
- M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
- 100);
- M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
- } else {
- M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
- 100);
- M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
- 100);
- M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
- }
- }
-
-CLEANUP:
- mp_clear(&one);
- mp_clear(&order_1);
- mp_clear(&gx);
- mp_clear(&gy);
- mp_clear(&rx);
- mp_clear(&ry);
- mp_clear(&n);
- if (res != MP_OKAY) {
- printf(" Error: exiting with error value %i\n", res);
- }
- return res;
-}
-
-/* Prints help information. */
-void
-printUsage()
-{
- printf("Usage: ecp_test [--print] [--time]\n");
- printf(" --print Print out results of each point arithmetic test.\n");
- printf(" --time Benchmark point operations and print results.\n");
-}
-
-/* Performs tests of elliptic curve cryptography over prime fields If
- * tests fail, then it prints an error message, aborts, and returns an
- * error code. Otherwise, returns 0. */
-int
-main(int argv, char **argc)
-{
-
- int ectestTime = 0;
- int ectestPrint = 0;
- int i;
- ECGroup *group = NULL;
- ECCurveParams *params = NULL;
- mp_err res;
-
- /* read command-line arguments */
- for (i = 1; i < argv; i++) {
- if ((strcasecmp(argc[i], "time") == 0) || (strcasecmp(argc[i], "-time") == 0) || (strcasecmp(argc[i], "--time") == 0)) {
- ectestTime = 1;
- } else if ((strcasecmp(argc[i], "print") == 0) || (strcasecmp(argc[i], "-print") == 0) || (strcasecmp(argc[i], "--print") == 0)) {
- ectestPrint = 1;
- } else {
- printUsage();
- return 0;
- }
- }
-
- /* generic arithmetic tests */
- ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
-
- /* specific arithmetic tests */
- ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
- ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
- ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
- ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
- ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
- ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
- ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
- ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
- ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
- ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
- ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
- ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
- ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
- ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
- ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
- ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
- ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
- ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
- ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
- ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
- ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
- ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
- ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
- ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
- ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
- ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
- ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
-
-CLEANUP:
- EC_FreeCurveParams(params);
- ECGroup_free(group);
- if (res != MP_OKAY) {
- printf("Error: exiting with error value %i\n", res);
- }
- return res;
-}
diff --git a/nss/lib/freebl/ecl/uint128.c b/nss/lib/freebl/ecl/uint128.c
index 22cbd02..5465875 100644
--- a/nss/lib/freebl/ecl/uint128.c
+++ b/nss/lib/freebl/ecl/uint128.c
@@ -31,6 +31,9 @@ init128x(uint64_t x)
return ret;
}
+#define CONSTANT_TIME_CARRY(a, b) \
+ ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1))
+
/* arithmetic */
uint128_t
@@ -38,7 +41,7 @@ add128(uint128_t a, uint128_t b)
{
uint128_t ret;
ret.lo = a.lo + b.lo;
- ret.hi = a.hi + b.hi + (ret.lo < b.lo);
+ ret.hi = a.hi + b.hi + CONSTANT_TIME_CARRY(ret.lo, b.lo);
return ret;
}
diff --git a/nss/lib/freebl/exports.gyp b/nss/lib/freebl/exports.gyp
index ef81685..aded6bf 100644
--- a/nss/lib/freebl/exports.gyp
+++ b/nss/lib/freebl/exports.gyp
@@ -33,6 +33,7 @@
'ec.h',
'ecl/ecl-curve.h',
'ecl/ecl.h',
+ 'ecl/eclt.h',
'hmacct.h',
'secmpi.h',
'secrng.h'
diff --git a/nss/lib/freebl/freebl.gyp b/nss/lib/freebl/freebl.gyp
index f5ae232..f754742 100644
--- a/nss/lib/freebl/freebl.gyp
+++ b/nss/lib/freebl/freebl.gyp
@@ -32,121 +32,55 @@
'<(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.
{
- 'target_name': '<(freebl_name)',
- 'type': 'shared_library',
- 'sources': [
- 'aeskeywrap.c',
- 'alg2268.c',
- 'alghmac.c',
- 'arcfive.c',
- 'arcfour.c',
- 'camellia.c',
- 'chacha20poly1305.c',
- 'ctr.c',
- 'cts.c',
- 'des.c',
- 'desblapi.c',
- 'dh.c',
- 'drbg.c',
- 'dsa.c',
- 'ec.c',
- 'ecdecode.c',
- 'ecl/ec_naf.c',
- 'ecl/ecl.c',
- 'ecl/ecl_curve.c',
- 'ecl/ecl_gf.c',
- 'ecl/ecl_mult.c',
- 'ecl/ecp_25519.c',
- 'ecl/ecp_256.c',
- 'ecl/ecp_256_32.c',
- 'ecl/ecp_384.c',
- 'ecl/ecp_521.c',
- 'ecl/ecp_aff.c',
- 'ecl/ecp_jac.c',
- 'ecl/ecp_jm.c',
- 'ecl/ecp_mont.c',
- 'fipsfreebl.c',
- 'freeblver.c',
- 'gcm.c',
- 'hmacct.c',
- 'jpake.c',
- 'ldvector.c',
- 'md2.c',
- 'md5.c',
- 'mpi/mp_gf2m.c',
- 'mpi/mpcpucache.c',
- 'mpi/mpi.c',
- 'mpi/mplogic.c',
- 'mpi/mpmontg.c',
- 'mpi/mpprime.c',
- 'pqg.c',
- 'rawhash.c',
- 'rijndael.c',
- 'rsa.c',
- 'rsapkcs.c',
- 'seed.c',
- 'sha512.c',
- 'sha_fast.c',
- 'shvfy.c',
- 'sysrand.c',
- 'tlsprfalg.c'
+ 'target_name': 'freebl_static',
+ 'type': 'static_library',
+ 'includes': [
+ 'freebl_base.gypi',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'OS=="linux"', {
- 'sources': [
- 'nsslowhash.c',
- 'stubs.c',
+ 'defines!': [
+ 'FREEBL_NO_DEPEND',
+ 'FREEBL_LOWHASH',
+ 'USE_HW_AES',
+ 'INTEL_GCM',
],
'conditions': [
- [ 'test_build==1', {
- 'dependencies': [
- '<(DEPTH)/lib/util/util.gyp:nssutil3',
- ],
- }],
[ 'target_arch=="x64"', {
- 'sources': [
- 'arcfour-amd64-gas.s',
+ # The AES assembler code doesn't work in static test builds.
+ # The linker complains about non-relocatable code, and I
+ # currently don't know how to fix this properly.
+ 'sources!': [
'intel-aes.s',
'intel-gcm.s',
- 'mpi/mpi_amd64.c',
- 'mpi/mpi_amd64_gas.s',
- 'mpi/mp_comba.c',
- ],
- 'dependencies': [
- 'intel-gcm-wrap_c_lib',
- ],
- 'conditions': [
- [ 'cc_is_clang==1', {
- 'cflags': [
- '-no-integrated-as',
- ],
- 'cflags_mozilla': [
- '-no-integrated-as',
- ],
- 'asflags_mozilla': [
- '-no-integrated-as',
- ],
- }],
- ],
- }],
- [ 'target_arch=="ia32"', {
- 'sources': [
- 'mpi/mpi_x86.s',
- ],
- }],
- [ 'target_arch=="arm"', {
- 'sources': [
- 'mpi/mpi_arm.c',
],
}],
],
- }, {
- # not Linux
+ }],
+ ],
+ },
+ {
+ 'target_name': '<(freebl_name)',
+ 'type': 'shared_library',
+ 'includes': [
+ 'freebl_base.gypi',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ ],
+ 'conditions': [
+ [ 'OS!="linux" and OS!="android"', {
'conditions': [
[ 'moz_fold_libs==0', {
'dependencies': [
- '../util/util.gyp:nssutil3',
+ '<(DEPTH)/lib/util/util.gyp:nssutil3',
],
}, {
'libraries': [
@@ -154,97 +88,23 @@
],
}],
],
- }],
- [ 'OS=="win"', {
- 'sources': [
- #TODO: building with mingw should not need this.
- 'ecl/uint128.c',
- #TODO: clang-cl needs -msse3 here
- 'intel-gcm-wrap.c',
- ],
- 'libraries': [
- 'advapi32.lib',
- ],
- 'conditions': [
- [ 'target_arch=="x64"', {
- 'sources': [
- 'arcfour-amd64-masm.asm',
- 'mpi/mpi_amd64.c',
- 'mpi/mpi_amd64_masm.asm',
- 'mpi/mp_comba_amd64_masm.asm',
- 'intel-aes-x64-masm.asm',
- 'intel-gcm-x64-masm.asm',
- ],
- }, {
- # not x64
- 'sources': [
- 'mpi/mpi_x86_asm.c',
- 'intel-aes-x86-masm.asm',
- 'intel-gcm-x86-masm.asm',
- ],
- }],
- ],
- }],
- ['target_arch=="ia32" or target_arch=="x64"', {
- 'sources': [
- # All intel architectures get the 64 bit version
- 'ecl/curve25519_64.c',
- ],
- }, {
- 'sources': [
- # All non intel architectures get the generic 32 bit implementation (slow!)
- 'ecl/curve25519_32.c',
+ }, 'target_arch=="x64"', {
+ 'dependencies': [
+ 'intel-gcm-wrap_c_lib',
],
}],
- #TODO uint128.c
- [ 'disable_chachapoly==0', {
- 'conditions': [
- [ 'OS!="win" and target_arch=="x64"', {
- 'sources': [
- 'chacha20_vec.c',
- 'poly1305-donna-x64-sse2-incremental-source.c',
- ],
- }, {
- # not x64
- 'sources': [
- 'chacha20.c',
- 'poly1305.c',
- ],
- }],
+ [ 'OS=="win" and cc_is_clang==1', {
+ 'dependencies': [
+ 'intel-gcm-wrap_c_lib',
],
}],
- [ 'fuzz==1', {
+ [ 'OS=="linux"', {
'sources': [
- 'det_rng.c',
- ],
- 'defines': [
- 'UNSAFE_FUZZER_MODE',
- ],
- }],
- [ 'test_build==1', {
- 'defines': [
- 'CT_VERIF',
- ],
- }],
- [ 'OS=="mac"', {
- 'conditions': [
- [ 'target_arch=="ia32"', {
- 'sources': [
- 'mpi/mpi_sse2.s',
- ],
- 'defines': [
- 'MP_USE_UINT_DIGIT',
- 'MP_ASSEMBLY_MULTIPLY',
- 'MP_ASSEMBLY_SQUARE',
- 'MP_ASSEMBLY_DIV_2DX1D',
- ],
- }],
+ 'nsslowhash.c',
+ 'stubs.c',
],
}],
],
- 'dependencies': [
- '<(DEPTH)/exports.gyp:nss_exports',
- ],
'variables': {
'conditions': [
[ 'OS=="linux"', {
@@ -254,9 +114,6 @@
}],
]
},
- 'ldflags': [
- '-Wl,-Bsymbolic'
- ]
},
],
'conditions': [
@@ -301,8 +158,6 @@
'VCCLCompilerTool': {
#TODO: -Ox optimize flags
'PreprocessorDefinitions': [
- 'NSS_X86_OR_X64',
- 'NSS_X86',
'MP_ASSEMBLY_MULTIPLY',
'MP_ASSEMBLY_SQUARE',
'MP_ASSEMBLY_DIV_2DX1D',
@@ -319,9 +174,7 @@
'VCCLCompilerTool': {
#TODO: -Ox optimize flags
'PreprocessorDefinitions': [
- 'NSS_USE_64',
- 'NSS_X86_OR_X64',
- 'NSS_X64',
+ # Should be copied to mingw defines below
'MP_IS_LITTLE_ENDIAN',
'NSS_BEVAND_ARCFOUR',
'MPI_AMD64',
@@ -333,13 +186,21 @@
},
},
}],
+ [ 'cc_use_gnu_ld==1 and OS=="win" and target_arch=="x64"', {
+ 'defines': [
+ 'MP_IS_LITTLE_ENDIAN',
+ 'NSS_BEVAND_ARCFOUR',
+ 'MPI_AMD64',
+ 'MP_ASSEMBLY_MULTIPLY',
+ 'NSS_USE_COMBA',
+ 'USE_HW_AES',
+ 'INTEL_GCM',
+ ],
+ }],
[ 'OS!="win"', {
'conditions': [
- [ 'target_arch=="x64"', {
+ [ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
'defines': [
- 'NSS_USE_64',
- 'NSS_X86_OR_X64',
- 'NSS_X64',
# The Makefile does version-tests on GCC, but we're not doing that here.
'HAVE_INT128_SUPPORT',
],
@@ -348,24 +209,16 @@
'ecl/uint128.c',
],
}],
- [ 'target_arch=="ia32"', {
- 'defines': [
- 'NSS_X86_OR_X64',
- 'NSS_X86',
- ],
- }],
],
}],
[ 'OS=="linux"', {
'defines': [
'FREEBL_LOWHASH',
+ 'FREEBL_NO_DEPEND',
],
+ }],
+ [ 'OS=="linux" or OS=="android"', {
'conditions': [
- [ 'test_build==0', {
- 'defines': [
- 'FREEBL_NO_DEPEND',
- ],
- }],
[ 'target_arch=="x64"', {
'defines': [
'MP_IS_LITTLE_ENDIAN',
@@ -375,7 +228,7 @@
'NSS_USE_COMBA',
],
}],
- [ 'target_arch=="x64" and use_msan==0', {
+ [ 'target_arch=="x64"', {
'defines': [
'USE_HW_AES',
'INTEL_GCM',
@@ -396,6 +249,7 @@
'MP_ASSEMBLY_SQUARE',
'MP_USE_UINT_DIGIT',
'SHA_NO_LONG_LONG',
+ 'ARMHF',
],
}],
],
diff --git a/nss/lib/freebl/freebl_base.gypi b/nss/lib/freebl/freebl_base.gypi
new file mode 100644
index 0000000..027aa27
--- /dev/null
+++ b/nss/lib/freebl/freebl_base.gypi
@@ -0,0 +1,201 @@
+# 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/.
+{
+ 'sources': [
+ 'aeskeywrap.c',
+ 'alg2268.c',
+ 'alghmac.c',
+ 'arcfive.c',
+ 'arcfour.c',
+ 'camellia.c',
+ 'chacha20poly1305.c',
+ 'ctr.c',
+ 'cts.c',
+ 'des.c',
+ 'desblapi.c',
+ 'dh.c',
+ 'drbg.c',
+ 'dsa.c',
+ 'ec.c',
+ 'ecdecode.c',
+ 'ecl/ec_naf.c',
+ 'ecl/ecl.c',
+ 'ecl/ecl_gf.c',
+ 'ecl/ecl_mult.c',
+ 'ecl/ecp_25519.c',
+ 'ecl/ecp_256.c',
+ 'ecl/ecp_256_32.c',
+ 'ecl/ecp_384.c',
+ 'ecl/ecp_521.c',
+ 'ecl/ecp_aff.c',
+ 'ecl/ecp_jac.c',
+ 'ecl/ecp_jm.c',
+ 'ecl/ecp_mont.c',
+ 'fipsfreebl.c',
+ 'blinit.c',
+ 'freeblver.c',
+ 'gcm.c',
+ 'hmacct.c',
+ 'jpake.c',
+ 'ldvector.c',
+ 'md2.c',
+ 'md5.c',
+ 'mpi/mp_gf2m.c',
+ 'mpi/mpcpucache.c',
+ 'mpi/mpi.c',
+ 'mpi/mplogic.c',
+ 'mpi/mpmontg.c',
+ 'mpi/mpprime.c',
+ 'pqg.c',
+ 'rawhash.c',
+ 'rijndael.c',
+ 'rsa.c',
+ 'rsapkcs.c',
+ 'seed.c',
+ 'sha512.c',
+ 'sha_fast.c',
+ 'shvfy.c',
+ 'sysrand.c',
+ 'tlsprfalg.c'
+ ],
+ 'conditions': [
+ [ 'OS=="linux" or OS=="android"', {
+ 'conditions': [
+ [ 'target_arch=="x64"', {
+ 'sources': [
+ 'arcfour-amd64-gas.s',
+ 'intel-aes.s',
+ 'intel-gcm.s',
+ 'mpi/mpi_amd64.c',
+ 'mpi/mpi_amd64_gas.s',
+ 'mpi/mp_comba.c',
+ ],
+ 'conditions': [
+ [ 'cc_is_clang==1', {
+ 'cflags': [
+ '-no-integrated-as',
+ ],
+ 'cflags_mozilla': [
+ '-no-integrated-as',
+ ],
+ 'asflags_mozilla': [
+ '-no-integrated-as',
+ ],
+ }],
+ ],
+ }],
+ [ 'target_arch=="ia32"', {
+ 'sources': [
+ 'mpi/mpi_x86.s',
+ ],
+ }],
+ [ 'target_arch=="arm"', {
+ 'sources': [
+ 'mpi/mpi_arm.c',
+ ],
+ }],
+ ],
+ }],
+ [ 'OS=="win"', {
+ 'sources': [
+ #TODO: building with mingw should not need this.
+ 'ecl/uint128.c',
+ ],
+ 'libraries': [
+ 'advapi32.lib',
+ ],
+ 'conditions': [
+ [ 'cc_use_gnu_ld!=1 and target_arch=="x64"', {
+ 'sources': [
+ 'arcfour-amd64-masm.asm',
+ 'mpi/mpi_amd64.c',
+ 'mpi/mpi_amd64_masm.asm',
+ 'mpi/mp_comba_amd64_masm.asm',
+ 'intel-aes-x64-masm.asm',
+ 'intel-gcm-x64-masm.asm',
+ ],
+ }],
+ [ 'cc_use_gnu_ld!=1 and target_arch!="x64"', {
+ # not x64
+ 'sources': [
+ 'mpi/mpi_x86_asm.c',
+ 'intel-aes-x86-masm.asm',
+ 'intel-gcm-x86-masm.asm',
+ ],
+ }],
+ [ 'cc_is_clang!=1', {
+ # MSVC
+ 'sources': [
+ 'intel-gcm-wrap.c',
+ ],
+ }],
+ ],
+ }],
+ ['target_arch=="ia32" or target_arch=="x64"', {
+ 'sources': [
+ # All intel architectures get the 64 bit version
+ 'ecl/curve25519_64.c',
+ ],
+ }, {
+ 'sources': [
+ # All non intel architectures get the generic 32 bit implementation (slow!)
+ 'ecl/curve25519_32.c',
+ ],
+ }],
+ #TODO uint128.c
+ [ 'disable_chachapoly==0', {
+ 'conditions': [
+ [ 'OS!="win" and target_arch=="x64"', {
+ 'sources': [
+ 'chacha20_vec.c',
+ 'poly1305-donna-x64-sse2-incremental-source.c',
+ ],
+ }, {
+ # not x64
+ 'sources': [
+ 'chacha20.c',
+ 'poly1305.c',
+ ],
+ }],
+ ],
+ }],
+ [ 'fuzz==1', {
+ 'sources!': [ 'drbg.c' ],
+ 'sources': [ 'det_rng.c' ],
+ }],
+ [ 'fuzz_tls==1', {
+ 'defines': [
+ 'UNSAFE_FUZZER_MODE',
+ ],
+ }],
+ [ 'ct_verif==1', {
+ 'defines': [
+ 'CT_VERIF',
+ ],
+ }],
+ [ 'only_dev_random==1', {
+ 'defines': [
+ 'SEED_ONLY_DEV_URANDOM',
+ ]
+ }],
+ [ 'OS=="mac"', {
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'sources': [
+ 'mpi/mpi_sse2.s',
+ ],
+ 'defines': [
+ 'MP_USE_UINT_DIGIT',
+ 'MP_ASSEMBLY_MULTIPLY',
+ 'MP_ASSEMBLY_SQUARE',
+ 'MP_ASSEMBLY_DIV_2DX1D',
+ ],
+ }],
+ ],
+ }],
+ ],
+ 'ldflags': [
+ '-Wl,-Bsymbolic'
+ ],
+}
diff --git a/nss/lib/freebl/ldvector.c b/nss/lib/freebl/ldvector.c
index fb986a6..2447a0c 100644
--- a/nss/lib/freebl/ldvector.c
+++ b/nss/lib/freebl/ldvector.c
@@ -294,9 +294,13 @@ static const struct FREEBLVectorStr vector =
ChaCha20Poly1305_CreateContext,
ChaCha20Poly1305_DestroyContext,
ChaCha20Poly1305_Seal,
- ChaCha20Poly1305_Open
+ ChaCha20Poly1305_Open,
/* End of Version 3.018 */
+
+ EC_GetPointSize
+
+ /* End of Version 3.019 */
};
const FREEBLVector*
diff --git a/nss/lib/freebl/loader.c b/nss/lib/freebl/loader.c
index 84876c1..792171b 100644
--- a/nss/lib/freebl/loader.c
+++ b/nss/lib/freebl/loader.c
@@ -2116,3 +2116,11 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx,
ctx, output, outputLen, maxOutputLen, input, inputLen,
nonce, nonceLen, ad, adLen);
}
+
+int
+EC_GetPointSize(const ECParams *params)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return SECFailure;
+ return (vector->p_EC_GetPointSize)(params);
+}
diff --git a/nss/lib/freebl/loader.h b/nss/lib/freebl/loader.h
index ced03b5..ed392cc 100644
--- a/nss/lib/freebl/loader.h
+++ b/nss/lib/freebl/loader.h
@@ -10,7 +10,7 @@
#include "blapi.h"
-#define FREEBL_VERSION 0x0312
+#define FREEBL_VERSION 0x0313
struct FREEBLVectorStr {
@@ -732,6 +732,10 @@ struct FREEBLVectorStr {
/* Version 3.018 came to here */
+ int (*p_EC_GetPointSize)(const ECParams *);
+
+ /* Version 3.019 came to here */
+
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
};
diff --git a/nss/lib/freebl/manifest.mn b/nss/lib/freebl/manifest.mn
index 1ef9839..bf81442 100644
--- a/nss/lib/freebl/manifest.mn
+++ b/nss/lib/freebl/manifest.mn
@@ -94,6 +94,7 @@ PRIVATE_EXPORTS = \
ec.h \
ecl.h \
ecl-curve.h \
+ eclt.h \
$(NULL)
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
@@ -102,7 +103,7 @@ MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
ECL_HDRS = ecl-exp.h ecl.h ecp.h ecl-priv.h
ifndef NSS_DISABLE_ECC
-ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
+ECL_SRCS = ecl.c ecl_mult.c ecl_gf.c \
ecp_aff.c ecp_jac.c ecp_mont.c \
ec_naf.c ecp_jm.c ecp_256.c ecp_384.c ecp_521.c \
ecp_256_32.c ecp_25519.c
@@ -131,6 +132,7 @@ CSRCS = \
chacha20poly1305.c \
cts.c \
ctr.c \
+ blinit.c \
fipsfreebl.c \
gcm.c \
hmacct.c \
diff --git a/nss/lib/freebl/mpi/README b/nss/lib/freebl/mpi/README
index 475549b..f1c66df 100644
--- a/nss/lib/freebl/mpi/README
+++ b/nss/lib/freebl/mpi/README
@@ -503,9 +503,6 @@ MP_MODARITH - Define true to include the modular arithmetic
in your application, you can set this to zero to
leave out all the modular routines.
-MP_NUMTH - Define true to include number theoretic functions
- such as mp_gcd(), mp_lcm(), and mp_invmod().
-
MP_LOGTAB - If true, the file "logtab.h" is included, which
is basically a static table of base 2 logarithms.
These are used to compute how big the buffers for
diff --git a/nss/lib/freebl/mpi/mpi-config.h b/nss/lib/freebl/mpi/mpi-config.h
index f365592..c6f72b2 100644
--- a/nss/lib/freebl/mpi/mpi-config.h
+++ b/nss/lib/freebl/mpi/mpi-config.h
@@ -24,10 +24,6 @@
#define MP_MODARITH 1 /* include modular arithmetic ? */
#endif
-#ifndef MP_NUMTH
-#define MP_NUMTH 1 /* include number theoretic functions? */
-#endif
-
#ifndef MP_LOGTAB
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif
diff --git a/nss/lib/freebl/mpi/mpi.c b/nss/lib/freebl/mpi/mpi.c
index f6f7543..f7784c8 100644
--- a/nss/lib/freebl/mpi/mpi.c
+++ b/nss/lib/freebl/mpi/mpi.c
@@ -1695,7 +1695,6 @@ mp_iseven(const mp_int *a)
/*------------------------------------------------------------------------*/
/* {{{ Number theoretic functions */
-#if MP_NUMTH
/* {{{ mp_gcd(a, b, c) */
/*
@@ -2376,7 +2375,6 @@ mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
} /* end mp_invmod() */
/* }}} */
-#endif /* if MP_NUMTH */
/* }}} */
@@ -2861,6 +2859,9 @@ void
s_mp_exch(mp_int *a, mp_int *b)
{
mp_int tmp;
+ if (!a || !b) {
+ return;
+ }
tmp = *a;
*a = *b;
@@ -4088,7 +4089,7 @@ s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
}
#endif
-#if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) && !defined(MP_ASSEMBLY_DIV_2DX1D)
+#if !defined(MP_ASSEMBLY_DIV_2DX1D)
/*
** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
** so its high bit is 1. This code is from NSPR.
@@ -4166,11 +4167,7 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
mp_int *quot) /* i: 0; o: quotient */
{
mp_int part, t;
-#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
- mp_word q_msd;
-#else
mp_digit q_msd;
-#endif
mp_err res;
mp_digit d;
mp_digit div_msd;
@@ -4215,7 +4212,7 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
MP_USED(&part) = MP_USED(div);
/* We have now truncated the part of the remainder to the same length as
- * the divisor. If part is smaller than div, extend part by one digit. */
+ * the divisor. If part is smaller than div, extend part by one digit. */
if (s_mp_cmp(&part, div) < 0) {
--unusedRem;
#if MP_ARGCHK == 2
@@ -4232,18 +4229,12 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
div_msd = MP_DIGIT(div, MP_USED(div) - 1);
if (!partExtended) {
/* In this case, q_msd /= div_msd is always 1. First, since div_msd is
- * normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since
- * we didn't extend part, q_msd >= div_msd. Therefore we know that
- * div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we
- * get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */
+ * normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since
+ * we didn't extend part, q_msd >= div_msd. Therefore we know that
+ * div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we
+ * get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */
q_msd = 1;
} else {
-#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
- q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
- q_msd /= div_msd;
- if (q_msd == RADIX)
- --q_msd;
-#else
if (q_msd == div_msd) {
q_msd = MP_DIGIT_MAX;
} else {
@@ -4251,7 +4242,6 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
MP_CHECKOK(s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
div_msd, &q_msd, &r));
}
-#endif
}
#if MP_ARGCHK == 2
assert(q_msd > 0); /* This case should never occur any more. */
@@ -4261,15 +4251,15 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
/* See what that multiplies out to */
mp_copy(div, &t);
- MP_CHECKOK(s_mp_mul_d(&t, (mp_digit)q_msd));
+ MP_CHECKOK(s_mp_mul_d(&t, q_msd));
/*
- If it's too big, back it off. We should not have to do this
- more than once, or, in rare cases, twice. Knuth describes a
- method by which this could be reduced to a maximum of once, but
- I didn't implement that here.
- * When using s_mpv_div_2dx1d, we may have to do this 3 times.
- */
+ If it's too big, back it off. We should not have to do this
+ more than once, or, in rare cases, twice. Knuth describes a
+ method by which this could be reduced to a maximum of once, but
+ I didn't implement that here.
+ When using s_mpv_div_2dx1d, we may have to do this 3 times.
+ */
for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
--q_msd;
MP_CHECKOK(s_mp_sub(&t, div)); /* t -= div */
@@ -4284,11 +4274,11 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
s_mp_clamp(rem);
/*
- Include the digit in the quotient. We allocated enough memory
- for any quotient we could ever possibly get, so we should not
- have to check for failures here
- */
- MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
+ Include the digit in the quotient. We allocated enough memory
+ for any quotient we could ever possibly get, so we should not
+ have to check for failures here
+ */
+ MP_DIGIT(quot, unusedRem) = q_msd;
}
/* Denormalize remainder */
diff --git a/nss/lib/freebl/mpi/mpi.h b/nss/lib/freebl/mpi/mpi.h
index 64ffe75..97af0f0 100644
--- a/nss/lib/freebl/mpi/mpi.h
+++ b/nss/lib/freebl/mpi/mpi.h
@@ -225,13 +225,11 @@ int mp_isodd(const mp_int *a);
int mp_iseven(const mp_int *a);
/* Number theoretic */
-#if MP_NUMTH
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
-#endif /* end MP_NUMTH */
/* Input and output */
#if MP_IOFUNC
diff --git a/nss/lib/freebl/mpi/mpprime.c b/nss/lib/freebl/mpi/mpprime.c
index 5828719..9d6232c 100644
--- a/nss/lib/freebl/mpi/mpprime.c
+++ b/nss/lib/freebl/mpi/mpprime.c
@@ -402,8 +402,7 @@ mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
#define SIEVE_SIZE 32 * 1024
mp_err
-mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
- unsigned long *nTries)
+mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong)
{
mp_digit np;
mp_err res;
@@ -548,8 +547,6 @@ mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
CLEANUP:
mp_clear(&trial);
mp_clear(&q);
- if (nTries)
- *nTries += i;
if (sieve != NULL) {
memset(sieve, 0, SIEVE_SIZE);
free(sieve);
diff --git a/nss/lib/freebl/mpi/mpprime.h b/nss/lib/freebl/mpi/mpprime.h
index c47c618..acd888d 100644
--- a/nss/lib/freebl/mpi/mpprime.h
+++ b/nss/lib/freebl/mpi/mpprime.h
@@ -13,6 +13,8 @@
#include "mpi.h"
+SEC_BEGIN_PROTOS
+
extern const int prime_tab_size; /* number of primes available */
extern const mp_digit prime_tab[];
@@ -32,7 +34,8 @@ mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
mp_err mpp_pprime(mp_int *a, int nt);
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
unsigned char *sieve, mp_size nSieve);
-mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
- unsigned long *nTries);
+mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong);
+
+SEC_END_PROTOS
#endif /* end _H_MP_PRIME_ */
diff --git a/nss/lib/freebl/os2_rand.c b/nss/lib/freebl/os2_rand.c
deleted file mode 100644
index 407b080..0000000
--- a/nss/lib/freebl/os2_rand.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/* 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/. */
-
-#define INCL_DOS
-#define INCL_DOSERRORS
-#include <os2.h>
-#include "secrng.h"
-#include "prerror.h"
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-#include <sys/stat.h>
-
-static BOOL
-clockTickTime(unsigned long *phigh, unsigned long *plow)
-{
- APIRET rc = NO_ERROR;
- QWORD qword = { 0, 0 };
-
- rc = DosTmrQueryTime(&qword);
- if (rc != NO_ERROR)
- return FALSE;
-
- *phigh = qword.ulHi;
- *plow = qword.ulLo;
-
- return TRUE;
-}
-
-size_t
-RNG_GetNoise(void *buf, size_t maxbuf)
-{
- unsigned long high = 0;
- unsigned long low = 0;
- clock_t val = 0;
- int n = 0;
- int nBytes = 0;
- time_t sTime;
-
- if (maxbuf <= 0)
- return 0;
-
- clockTickTime(&high, &low);
-
- /* get the maximally changing bits first */
- nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
- memcpy(buf, &low, nBytes);
- n += nBytes;
- maxbuf -= nBytes;
-
- if (maxbuf <= 0)
- return n;
-
- nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
- memcpy(((char *)buf) + n, &high, nBytes);
- n += nBytes;
- maxbuf -= nBytes;
-
- if (maxbuf <= 0)
- return n;
-
- /* get the number of milliseconds that have elapsed since application started */
- val = clock();
-
- nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
- memcpy(((char *)buf) + n, &val, nBytes);
- n += nBytes;
- maxbuf -= nBytes;
-
- if (maxbuf <= 0)
- return n;
-
- /* get the time in seconds since midnight Jan 1, 1970 */
- time(&sTime);
- nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
- memcpy(((char *)buf) + n, &sTime, nBytes);
- n += nBytes;
-
- return n;
-}
-
-static BOOL
-EnumSystemFiles(void (*func)(const char *))
-{
- APIRET rc;
- ULONG sysInfo = 0;
- char bootLetter[2];
- char sysDir[_MAX_PATH] = "";
- char filename[_MAX_PATH];
- HDIR hdir = HDIR_CREATE;
- ULONG numFiles = 1;
- FILEFINDBUF3 fileBuf = { 0 };
- ULONG buflen = sizeof(FILEFINDBUF3);
-
- if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
- sizeof(ULONG)) == NO_ERROR) {
- bootLetter[0] = sysInfo + 'A' - 1;
- bootLetter[1] = '\0';
- strcpy(sysDir, bootLetter);
- strcpy(sysDir + 1, ":\\OS2\\");
-
- strcpy(filename, sysDir);
- strcat(filename, "*.*");
- }
-
- rc = DosFindFirst(filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
- &numFiles, FIL_STANDARD);
- if (rc == NO_ERROR) {
- do {
- // pass the full pathname to the callback
- sprintf(filename, "%s%s", sysDir, fileBuf.achName);
- (*func)(filename);
-
- numFiles = 1;
- rc = DosFindNext(hdir, &fileBuf, buflen, &numFiles);
- if (rc != NO_ERROR && rc != ERROR_NO_MORE_FILES)
- printf("DosFindNext errod code = %d\n", rc);
- } while (rc == NO_ERROR);
-
- rc = DosFindClose(hdir);
- if (rc != NO_ERROR)
- printf("DosFindClose error code = %d", rc);
- } else
- printf("DosFindFirst error code = %d", rc);
-
- return TRUE;
-}
-
-static int dwNumFiles, dwReadEvery, dwFileToRead = 0;
-
-static void
-CountFiles(const char *file)
-{
- dwNumFiles++;
-}
-
-static void
-ReadFiles(const char *file)
-{
- if ((dwNumFiles % dwReadEvery) == 0)
- RNG_FileForRNG(file);
-
- dwNumFiles++;
-}
-
-static void
-ReadSingleFile(const char *filename)
-{
- unsigned char buffer[1024];
- FILE *file;
-
- file = fopen((char *)filename, "rb");
- if (file != NULL) {
- while (fread(buffer, 1, sizeof(buffer), file) > 0)
- ;
- fclose(file);
- }
-}
-
-static void
-ReadOneFile(const char *file)
-{
- if (dwNumFiles == dwFileToRead) {
- ReadSingleFile(file);
- }
-
- dwNumFiles++;
-}
-
-static void
-ReadSystemFiles(void)
-{
- // first count the number of files
- dwNumFiles = 0;
- if (!EnumSystemFiles(CountFiles))
- return;
-
- RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
-
- // now read 10 files
- if (dwNumFiles == 0)
- return;
-
- dwReadEvery = dwNumFiles / 10;
- if (dwReadEvery == 0)
- dwReadEvery = 1; // less than 10 files
-
- dwNumFiles = 0;
- EnumSystemFiles(ReadFiles);
-}
-
-void
-RNG_SystemInfoForRNG(void)
-{
- unsigned long *plong = 0;
- PTIB ptib;
- PPIB ppib;
- APIRET rc = NO_ERROR;
- DATETIME dt;
- COUNTRYCODE cc = { 0 };
- COUNTRYINFO ci = { 0 };
- unsigned long actual = 0;
- char path[_MAX_PATH] = "";
- char fullpath[_MAX_PATH] = "";
- unsigned long pathlength = sizeof(path);
- FSALLOCATE fsallocate;
- FILESTATUS3 fstatus;
- unsigned long defaultdrive = 0;
- unsigned long logicaldrives = 0;
- unsigned long sysInfo[QSV_MAX] = { 0 };
- char buffer[20];
- int nBytes = 0;
-
- nBytes = RNG_GetNoise(buffer, sizeof(buffer));
- RNG_RandomUpdate(buffer, nBytes);
-
- /* allocate memory and use address and memory */
- plong = (unsigned long *)malloc(sizeof(*plong));
- RNG_RandomUpdate(&plong, sizeof(plong));
- RNG_RandomUpdate(plong, sizeof(*plong));
- free(plong);
-
- /* process info */
- rc = DosGetInfoBlocks(&ptib, &ppib);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(ptib, sizeof(*ptib));
- RNG_RandomUpdate(ppib, sizeof(*ppib));
- }
-
- /* time */
- rc = DosGetDateTime(&dt);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&dt, sizeof(dt));
- }
-
- /* country */
- rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&cc, sizeof(cc));
- RNG_RandomUpdate(&ci, sizeof(ci));
- RNG_RandomUpdate(&actual, sizeof(actual));
- }
-
- /* current directory */
- rc = DosQueryCurrentDir(0, path, &pathlength);
- strcat(fullpath, "\\");
- strcat(fullpath, path);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(fullpath, strlen(fullpath));
- // path info
- rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&fstatus, sizeof(fstatus));
- }
- }
-
- /* file system info */
- rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
- }
-
- /* drive info */
- rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
- RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
- }
-
- /* system info */
- rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG) * QSV_MAX);
- if (rc == NO_ERROR) {
- RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
- }
-
- // now let's do some files
- ReadSystemFiles();
-
- /* more noise */
- nBytes = RNG_GetNoise(buffer, sizeof(buffer));
- RNG_RandomUpdate(buffer, nBytes);
-}
-
-void
-RNG_FileForRNG(const char *filename)
-{
- struct stat stat_buf;
- unsigned char buffer[1024];
- FILE *file = 0;
- int nBytes = 0;
- static int totalFileBytes = 0;
-
- if (stat((char *)filename, &stat_buf) < 0)
- return;
-
- RNG_RandomUpdate((unsigned char *)&stat_buf, sizeof(stat_buf));
-
- file = fopen((char *)filename, "r");
- if (file != NULL) {
- for (;;) {
- size_t bytes = fread(buffer, 1, sizeof(buffer), file);
-
- if (bytes == 0)
- break;
-
- RNG_RandomUpdate(buffer, bytes);
- totalFileBytes += bytes;
- if (totalFileBytes > 250000)
- break;
- }
- fclose(file);
- }
-
- nBytes = RNG_GetNoise(buffer, 20);
- RNG_RandomUpdate(buffer, nBytes);
-}
-
-static void
-rng_systemJitter(void)
-{
- dwNumFiles = 0;
- EnumSystemFiles(ReadOneFile);
- dwFileToRead++;
- if (dwFileToRead >= dwNumFiles) {
- dwFileToRead = 0;
- }
-}
-
-size_t
-RNG_SystemRNG(void *dest, size_t maxLen)
-{
- return rng_systemFromNoise(dest, maxLen);
-}
diff --git a/nss/lib/freebl/rijndael.c b/nss/lib/freebl/rijndael.c
index 4bb1826..0c3ab58 100644
--- a/nss/lib/freebl/rijndael.c
+++ b/nss/lib/freebl/rijndael.c
@@ -26,17 +26,11 @@
#include "mpi.h"
#ifdef USE_HW_AES
-static int has_intel_aes = 0;
static PRBool use_hw_aes = PR_FALSE;
#ifdef INTEL_GCM
#include "intel-gcm.h"
-static int has_intel_avx = 0;
-static int has_intel_clmul = 0;
static PRBool use_hw_gcm = PR_FALSE;
-#if defined(_MSC_VER) && !defined(_M_IX86)
-#include <intrin.h> /* for _xgetbv() */
-#endif
#endif
#endif /* USE_HW_AES */
@@ -999,39 +993,6 @@ AES_AllocateContext(void)
return PORT_ZNew(AESContext);
}
-#ifdef INTEL_GCM
-/*
- * Adapted from the example code in "How to detect New Instruction support in
- * the 4th generation Intel Core processor family" by Max Locktyukhin.
- *
- * XGETBV:
- * Reads an extended control register (XCR) specified by ECX into EDX:EAX.
- */
-static PRBool
-check_xcr0_ymm()
-{
- PRUint32 xcr0;
-#if defined(_MSC_VER)
-#if defined(_M_IX86)
- __asm {
- mov ecx, 0
- xgetbv
- mov xcr0, eax
- }
-#else
- xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */
-#endif
-#else
- __asm__("xgetbv"
- : "=a"(xcr0)
- : "c"(0)
- : "%edx");
-#endif
- /* Check if xmm and ymm state are enabled in XCR0. */
- return (xcr0 & 6) == 6;
-}
-#endif
-
/*
** Initialize a new AES context suitable for AES encryption/decryption in
** the ECB or CBC mode.
@@ -1070,33 +1031,9 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
return SECFailure;
}
#ifdef USE_HW_AES
- if (has_intel_aes == 0) {
- unsigned long eax, ebx, ecx, edx;
- char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
-
- if (disable_hw_aes == NULL) {
- freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
- has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1;
-#ifdef INTEL_GCM
- has_intel_clmul = (ecx & (1 << 1)) != 0 ? 1 : -1;
- if ((ecx & (1 << 27)) != 0 && (ecx & (1 << 28)) != 0 &&
- check_xcr0_ymm()) {
- has_intel_avx = 1;
- } else {
- has_intel_avx = -1;
- }
-#endif
- } else {
- has_intel_aes = -1;
-#ifdef INTEL_GCM
- has_intel_avx = -1;
- has_intel_clmul = -1;
-#endif
- }
- }
- use_hw_aes = (PRBool)(has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16);
+ use_hw_aes = aesni_support() && (keysize % 8) == 0 && blocksize == 16;
#ifdef INTEL_GCM
- use_hw_gcm = (PRBool)(use_hw_aes && has_intel_avx > 0 && has_intel_clmul > 0);
+ use_hw_gcm = use_hw_aes && avx_support() && clmul_support();
#endif
#endif /* USE_HW_AES */
/* Nb = (block size in bits) / 32 */
diff --git a/nss/lib/freebl/rsa.c b/nss/lib/freebl/rsa.c
index ff8c40e..17d1d87 100644
--- a/nss/lib/freebl/rsa.c
+++ b/nss/lib/freebl/rsa.c
@@ -190,12 +190,12 @@ cleanup:
}
return rv;
}
-static SECStatus
+
+SECStatus
generate_prime(mp_int *prime, int primeLen)
{
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
- unsigned long counter = 0;
int piter;
unsigned char *pb = NULL;
pb = PORT_Alloc(primeLen);
@@ -208,7 +208,7 @@ generate_prime(mp_int *prime, int primeLen)
pb[0] |= 0xC0; /* set two high-order bits */
pb[primeLen - 1] |= 0x01; /* set low-order bit */
CHECK_MPI_OK(mp_read_unsigned_octets(prime, pb, primeLen));
- err = mpp_make_prime(prime, primeLen * 8, PR_FALSE, &counter);
+ err = mpp_make_prime(prime, primeLen * 8, PR_FALSE);
if (err != MP_NO)
goto cleanup;
/* keep going while err == MP_NO */
@@ -1236,7 +1236,10 @@ get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
* Now, search its list of ready blinding params for a usable one.
*/
while (0 != (bp = rsabp->bp)) {
- if (--(bp->counter) > 0) {
+#ifndef UNSAFE_FUZZER_MODE
+ if (--(bp->counter) > 0)
+#endif
+ {
/* Found a match and there are still remaining uses left */
/* Return the parameters */
CHECK_MPI_OK(mp_copy(&bp->f, f));
@@ -1548,7 +1551,7 @@ cleanup:
return rv;
}
-static SECStatus
+SECStatus
RSA_Init(void)
{
if (PR_CallOnce(&coBPInit, init_blinding_params_list) != PR_SUCCESS) {
@@ -1558,12 +1561,6 @@ RSA_Init(void)
return SECSuccess;
}
-SECStatus
-BL_Init(void)
-{
- return RSA_Init();
-}
-
/* cleanup at shutdown */
void
RSA_Cleanup(void)
diff --git a/nss/lib/freebl/rsapkcs.c b/nss/lib/freebl/rsapkcs.c
index 577fe1f..c8a15da 100644
--- a/nss/lib/freebl/rsapkcs.c
+++ b/nss/lib/freebl/rsapkcs.c
@@ -85,6 +85,25 @@ rsa_modulusLen(SECItem *modulus)
return modLen;
}
+static unsigned int
+rsa_modulusBits(SECItem *modulus)
+{
+ unsigned char byteZero = modulus->data[0];
+ unsigned int numBits = (modulus->len - 1) * 8;
+
+ if (byteZero == 0) {
+ numBits -= 8;
+ byteZero = modulus->data[1];
+ }
+
+ while (byteZero > 0) {
+ numBits++;
+ byteZero >>= 1;
+ }
+
+ return numBits;
+}
+
/*
* Format one block of data for public/private key encryption using
* the rules defined in PKCS #1.
@@ -962,12 +981,11 @@ failure:
* We use mHash instead of M as input.
* emBits from the RFC is just modBits - 1, see section 8.1.1.
* We only support MGF1 as the MGF.
- *
- * NOTE: this code assumes modBits is a multiple of 8.
*/
static SECStatus
emsa_pss_encode(unsigned char *em,
unsigned int emLen,
+ unsigned int emBits,
const unsigned char *mHash,
HASH_HashType hashAlg,
HASH_HashType maskHashAlg,
@@ -1032,7 +1050,7 @@ emsa_pss_encode(unsigned char *em,
PORT_Free(dbMask);
/* Step 11 */
- em[0] &= 0x7f;
+ em[0] &= 0xff >> (8 * emLen - emBits);
/* Step 12 */
em[emLen - 1] = 0xbc;
@@ -1046,13 +1064,12 @@ emsa_pss_encode(unsigned char *em,
* We use mHash instead of M as input.
* emBits from the RFC is just modBits - 1, see section 8.1.2.
* We only support MGF1 as the MGF.
- *
- * NOTE: this code assumes modBits is a multiple of 8.
*/
static SECStatus
emsa_pss_verify(const unsigned char *mHash,
const unsigned char *em,
unsigned int emLen,
+ unsigned int emBits,
HASH_HashType hashAlg,
HASH_HashType maskHashAlg,
unsigned int saltLen)
@@ -1063,15 +1080,22 @@ emsa_pss_verify(const unsigned char *mHash,
unsigned char *H_; /* H' from the RFC */
unsigned int i;
unsigned int dbMaskLen;
+ unsigned int zeroBits;
SECStatus rv;
hash = HASH_GetRawHashObject(hashAlg);
dbMaskLen = emLen - hash->length - 1;
- /* Step 3 + 4 + 6 */
+ /* Step 3 + 4 */
if ((emLen < (hash->length + saltLen + 2)) ||
- (em[emLen - 1] != 0xbc) ||
- ((em[0] & 0x80) != 0)) {
+ (em[emLen - 1] != 0xbc)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ return SECFailure;
+ }
+
+ /* Step 6 */
+ zeroBits = 8 * emLen - emBits;
+ if (em[0] >> (8 - zeroBits)) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
@@ -1091,7 +1115,7 @@ emsa_pss_verify(const unsigned char *mHash,
}
/* Step 9 */
- db[0] &= 0x7f;
+ db[0] &= 0xff >> zeroBits;
/* Step 10 */
for (i = 0; i < (dbMaskLen - saltLen - 1); i++) {
@@ -1156,7 +1180,9 @@ RSA_SignPSS(RSAPrivateKey *key,
{
SECStatus rv = SECSuccess;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
- unsigned char *pssEncoded = NULL;
+ unsigned int modulusBits = rsa_modulusBits(&key->modulus);
+ unsigned int emLen = modulusLen;
+ unsigned char *pssEncoded, *em;
if (maxOutputLen < modulusLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
@@ -1168,16 +1194,24 @@ RSA_SignPSS(RSAPrivateKey *key,
return SECFailure;
}
- pssEncoded = (unsigned char *)PORT_Alloc(modulusLen);
+ pssEncoded = em = (unsigned char *)PORT_Alloc(modulusLen);
if (pssEncoded == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
- rv = emsa_pss_encode(pssEncoded, modulusLen, input, hashAlg,
+
+ /* len(em) == ceil((modulusBits - 1) / 8). */
+ if (modulusBits % 8 == 1) {
+ em[0] = 0;
+ emLen--;
+ em++;
+ }
+ rv = emsa_pss_encode(em, emLen, modulusBits - 1, input, hashAlg,
maskHashAlg, salt, saltLength);
if (rv != SECSuccess)
goto done;
+ // This sets error codes upon failure.
rv = RSA_PrivateKeyOpDoubleChecked(key, output, pssEncoded);
*outputLen = modulusLen;
@@ -1198,7 +1232,9 @@ RSA_CheckSignPSS(RSAPublicKey *key,
{
SECStatus rv;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
- unsigned char *buffer;
+ unsigned int modulusBits = rsa_modulusBits(&key->modulus);
+ unsigned int emLen = modulusLen;
+ unsigned char *buffer, *em;
if (sigLen != modulusLen) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
@@ -1210,7 +1246,7 @@ RSA_CheckSignPSS(RSAPublicKey *key,
return SECFailure;
}
- buffer = (unsigned char *)PORT_Alloc(modulusLen);
+ buffer = em = (unsigned char *)PORT_Alloc(modulusLen);
if (!buffer) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
@@ -1223,14 +1259,18 @@ RSA_CheckSignPSS(RSAPublicKey *key,
return SECFailure;
}
- rv = emsa_pss_verify(hash, buffer, modulusLen, hashAlg,
+ /* len(em) == ceil((modulusBits - 1) / 8). */
+ if (modulusBits % 8 == 1) {
+ emLen--;
+ em++;
+ }
+ rv = emsa_pss_verify(hash, em, emLen, modulusBits - 1, hashAlg,
maskHashAlg, saltLength);
- PORT_Free(buffer);
+ PORT_Free(buffer);
return rv;
}
-/* XXX Doesn't set error code */
SECStatus
RSA_Sign(RSAPrivateKey *key,
unsigned char *output,
@@ -1239,34 +1279,34 @@ RSA_Sign(RSAPrivateKey *key,
const unsigned char *input,
unsigned int inputLen)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv = SECFailure;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
- SECItem formatted;
- SECItem unformatted;
+ SECItem formatted = { siBuffer, NULL, 0 };
+ SECItem unformatted = { siBuffer, (unsigned char *)input, inputLen };
- if (maxOutputLen < modulusLen)
- return SECFailure;
+ if (maxOutputLen < modulusLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ goto done;
+ }
- unformatted.len = inputLen;
- unformatted.data = (unsigned char *)input;
- formatted.data = NULL;
rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockPrivate,
&unformatted);
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
goto done;
+ }
+ // This sets error codes upon failure.
rv = RSA_PrivateKeyOpDoubleChecked(key, output, formatted.data);
*outputLen = modulusLen;
- goto done;
-
done:
- if (formatted.data != NULL)
+ if (formatted.data != NULL) {
PORT_ZFree(formatted.data, modulusLen);
+ }
return rv;
}
-/* XXX Doesn't set error code */
SECStatus
RSA_CheckSign(RSAPublicKey *key,
const unsigned char *sig,
@@ -1274,60 +1314,71 @@ RSA_CheckSign(RSAPublicKey *key,
const unsigned char *data,
unsigned int dataLen)
{
- SECStatus rv;
+ SECStatus rv = SECFailure;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
+
+ if (sigLen != modulusLen) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
- if (sigLen != modulusLen)
- goto failure;
/*
* 0x00 || BT || Pad || 0x00 || ActualData
*
* The "3" below is the first octet + the second octet + the 0x00
* octet that always comes just before the ActualData.
*/
- if (dataLen > modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))
- goto failure;
+ if (dataLen > modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ goto done;
+ }
buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
- if (!buffer)
- goto failure;
+ if (!buffer) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto done;
+ }
- rv = RSA_PublicKeyOp(key, buffer, sig);
- if (rv != SECSuccess)
- goto loser;
+ if (RSA_PublicKeyOp(key, buffer, sig) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
/*
* check the padding that was used
*/
if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
buffer[1] != (unsigned char)RSA_BlockPrivate) {
- goto loser;
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
}
for (i = 2; i < modulusLen - dataLen - 1; i++) {
- if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET)
- goto loser;
+ if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
+ }
+ if (buffer[i] != RSA_BLOCK_AFTER_PAD_OCTET) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
}
- if (buffer[i] != RSA_BLOCK_AFTER_PAD_OCTET)
- goto loser;
/*
* make sure we get the same results
*/
- if (PORT_Memcmp(buffer + modulusLen - dataLen, data, dataLen) != 0)
- goto loser;
-
- PORT_Free(buffer);
- return SECSuccess;
+ if (PORT_Memcmp(buffer + modulusLen - dataLen, data, dataLen) == 0) {
+ rv = SECSuccess;
+ }
-loser:
- PORT_Free(buffer);
-failure:
- return SECFailure;
+done:
+ if (buffer) {
+ PORT_Free(buffer);
+ }
+ return rv;
}
-/* XXX Doesn't set error code */
SECStatus
RSA_CheckSignRecover(RSAPublicKey *key,
unsigned char *output,
@@ -1336,21 +1387,27 @@ RSA_CheckSignRecover(RSAPublicKey *key,
const unsigned char *sig,
unsigned int sigLen)
{
- SECStatus rv;
+ SECStatus rv = SECFailure;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
- if (sigLen != modulusLen)
- goto failure;
+ if (sigLen != modulusLen) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
- if (!buffer)
- goto failure;
+ if (!buffer) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ goto done;
+ }
+
+ if (RSA_PublicKeyOp(key, buffer, sig) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
- rv = RSA_PublicKeyOp(key, buffer, sig);
- if (rv != SECSuccess)
- goto loser;
*outputLen = 0;
/*
@@ -1358,28 +1415,34 @@ RSA_CheckSignRecover(RSAPublicKey *key,
*/
if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
buffer[1] != (unsigned char)RSA_BlockPrivate) {
- goto loser;
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
}
for (i = 2; i < modulusLen; i++) {
if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
*outputLen = modulusLen - i - 1;
break;
}
- if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET)
- goto loser;
+ if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
+ }
+ if (*outputLen == 0) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto done;
+ }
+ if (*outputLen > maxOutputLen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ goto done;
}
- if (*outputLen == 0)
- goto loser;
- if (*outputLen > maxOutputLen)
- goto loser;
PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen);
+ rv = SECSuccess;
- PORT_Free(buffer);
- return SECSuccess;
-
-loser:
- PORT_Free(buffer);
-failure:
- return SECFailure;
+done:
+ if (buffer) {
+ PORT_Free(buffer);
+ }
+ return rv;
}
diff --git a/nss/lib/freebl/sysrand.c b/nss/lib/freebl/sysrand.c
index 0128fa0..763f6af 100644
--- a/nss/lib/freebl/sysrand.c
+++ b/nss/lib/freebl/sysrand.c
@@ -8,42 +8,11 @@
#include "seccomon.h"
-#ifndef XP_WIN
-static size_t rng_systemFromNoise(unsigned char *dest, size_t maxLen);
-#endif
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
+#if (defined(XP_UNIX) || defined(XP_BEOS)) && defined(SEED_ONLY_DEV_URANDOM)
+#include "unix_urandom.c"
+#elif defined(XP_UNIX) || defined(XP_BEOS)
#include "unix_rand.c"
#endif
#ifdef XP_WIN
#include "win_rand.c"
#endif
-#ifdef XP_OS2
-#include "os2_rand.c"
-#endif
-
-#ifndef XP_WIN
-/*
- * Normal RNG_SystemRNG() isn't available, use the system noise to collect
- * the required amount of entropy.
- */
-static size_t
-rng_systemFromNoise(unsigned char *dest, size_t maxLen)
-{
- size_t retBytes = maxLen;
-
- while (maxLen) {
- size_t nbytes = RNG_GetNoise(dest, maxLen);
-
- PORT_Assert(nbytes != 0);
-
- dest += nbytes;
- maxLen -= nbytes;
-
- /* some hw op to try to introduce more entropy into the next
- * RNG_GetNoise call */
- rng_systemJitter();
- }
- return retBytes;
-}
-#endif
diff --git a/nss/lib/freebl/unix_rand.c b/nss/lib/freebl/unix_rand.c
index ea3b6af..20c76ec 100644
--- a/nss/lib/freebl/unix_rand.c
+++ b/nss/lib/freebl/unix_rand.c
@@ -160,7 +160,7 @@ RNG_kstat(PRUint32 *fed)
#endif
-#if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) || defined(NETBSD) || defined(DARWIN) || defined(OPENBSD) || defined(NTO) || defined(__riscos__)
+#if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) || defined(NETBSD) || defined(DARWIN) || defined(OPENBSD) || defined(NTO) || defined(__riscos__) || defined(__GNU__) || defined(__FreeBSD_kernel__) || defined(__NetBSD_kernel__)
#include <sys/times.h>
#define getdtablesize() sysconf(_SC_OPEN_MAX)
@@ -682,134 +682,6 @@ RNG_GetNoise(void *buf, size_t maxbytes)
return n;
}
-#define SAFE_POPEN_MAXARGS 10 /* must be at least 2 */
-
-/*
- * safe_popen is static to this module and we know what arguments it is
- * called with. Note that this version only supports a single open child
- * process at any time.
- */
-static pid_t safe_popen_pid;
-static struct sigaction oldact;
-
-static FILE *
-safe_popen(char *cmd)
-{
- int p[2], fd, argc;
- pid_t pid;
- char *argv[SAFE_POPEN_MAXARGS + 1];
- FILE *fp;
- static char blank[] = " \t";
- static struct sigaction newact;
-
- if (pipe(p) < 0)
- return 0;
-
- fp = fdopen(p[0], "r");
- if (fp == 0) {
- close(p[0]);
- close(p[1]);
- return 0;
- }
-
- /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
- newact.sa_handler = SIG_DFL;
- newact.sa_flags = 0;
- sigfillset(&newact.sa_mask);
- sigaction(SIGCHLD, &newact, &oldact);
-
- pid = fork();
- switch (pid) {
- int ndesc;
-
- case -1:
- fclose(fp); /* this closes p[0], the fd associated with fp */
- close(p[1]);
- sigaction(SIGCHLD, &oldact, NULL);
- return 0;
-
- case 0:
- /* dup write-side of pipe to stderr and stdout */
- if (p[1] != 1)
- dup2(p[1], 1);
- if (p[1] != 2)
- dup2(p[1], 2);
-
- /*
- * close the other file descriptors, except stdin which we
- * try reassociating with /dev/null, first (bug 174993)
- */
- if (!freopen("/dev/null", "r", stdin))
- close(0);
- ndesc = getdtablesize();
- for (fd = PR_MIN(65536, ndesc); --fd > 2; close(fd))
- ;
-
- /* clean up environment in the child process */
- putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");
- putenv("SHELL=/bin/sh");
- putenv("IFS= \t");
-
- /*
- * The caller may have passed us a string that is in text
- * space. It may be illegal to modify the string
- */
- cmd = strdup(cmd);
- /* format argv */
- argv[0] = strtok(cmd, blank);
- argc = 1;
- while ((argv[argc] = strtok(0, blank)) != 0) {
- if (++argc == SAFE_POPEN_MAXARGS) {
- argv[argc] = 0;
- break;
- }
- }
-
- /* and away we go */
- execvp(argv[0], argv);
- exit(127);
- break;
-
- default:
- close(p[1]);
- break;
- }
-
- /* non-zero means there's a cmd running */
- safe_popen_pid = pid;
- return fp;
-}
-
-static int
-safe_pclose(FILE *fp)
-{
- pid_t pid;
- int status = -1, rv;
-
- if ((pid = safe_popen_pid) == 0)
- return -1;
- safe_popen_pid = 0;
-
- fclose(fp);
-
- /* yield the processor so the child gets some time to exit normally */
- PR_Sleep(PR_INTERVAL_NO_WAIT);
-
- /* if the child hasn't exited, kill it -- we're done with its output */
- while ((rv = waitpid(pid, &status, WNOHANG)) == -1 && errno == EINTR)
- ;
- if (rv == 0) {
- kill(pid, SIGKILL);
- while ((rv = waitpid(pid, &status, 0)) == -1 && errno == EINTR)
- ;
- }
-
- /* Reset SIGCHLD signal hander before returning */
- sigaction(SIGCHLD, &oldact, NULL);
-
- return status;
-}
-
#ifdef DARWIN
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE
@@ -817,15 +689,9 @@ safe_pclose(FILE *fp)
#endif
#endif
-/* Fork netstat to collect its output by default. Do not unset this unless
- * another source of entropy is available
- */
-#define DO_NETSTAT 1
-
void
RNG_SystemInfoForRNG(void)
{
- FILE *fp;
char buf[BUFSIZ];
size_t bytes;
const char *const *cp;
@@ -860,12 +726,6 @@ RNG_SystemInfoForRNG(void)
};
#endif
-#if defined(BSDI)
- static char netstat_ni_cmd[] = "netstat -nis";
-#else
- static char netstat_ni_cmd[] = "netstat -ni";
-#endif
-
GiveSystemInfo();
bytes = RNG_GetNoise(buf, sizeof(buf));
@@ -890,10 +750,12 @@ RNG_SystemInfoForRNG(void)
if (gethostname(buf, sizeof(buf)) == 0) {
RNG_RandomUpdate(buf, strlen(buf));
}
- GiveSystemInfo();
/* grab some data from system's PRNG before any other files. */
bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);
+ if (!bytes) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ }
/* If the user points us to a random file, pass it through the rng */
randfile = PR_GetEnvSecure("NSRANDFILE");
@@ -911,33 +773,12 @@ RNG_SystemInfoForRNG(void)
for (cp = files; *cp; cp++)
RNG_FileForRNG(*cp);
-/*
- * Bug 100447: On BSD/OS 4.2 and 4.3, we have problem calling safe_popen
- * in a pthreads environment. Therefore, we call safe_popen last and on
- * BSD/OS we do not call safe_popen when we succeeded in getting data
- * from /dev/urandom.
- *
- * Bug 174993: On platforms providing /dev/urandom, don't fork netstat
- * either, if data has been gathered successfully.
- */
-
#if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || defined(DARWIN) || defined(LINUX) || defined(HPUX)
if (bytes)
return;
#endif
#ifdef SOLARIS
-
-/*
- * On Solaris, NSS may be initialized automatically from libldap in
- * applications that are unaware of the use of NSS. safe_popen forks, and
- * sometimes creates issues with some applications' pthread_atfork handlers.
- * We always have /dev/urandom on Solaris 9 and above as an entropy source,
- * and for Solaris 8 we have the libkstat interface, so we don't need to
- * fork netstat.
- */
-
-#undef DO_NETSTAT
if (!bytes) {
/* On Solaris 8, /dev/urandom isn't available, so we use libkstat. */
PRUint32 kstat_bytes = 0;
@@ -948,15 +789,6 @@ RNG_SystemInfoForRNG(void)
PORT_Assert(bytes);
}
#endif
-
-#ifdef DO_NETSTAT
- fp = safe_popen(netstat_ni_cmd);
- if (fp != NULL) {
- while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
- RNG_RandomUpdate(buf, bytes);
- safe_pclose(fp);
- }
-#endif
}
#define TOTAL_FILE_LIMIT 1000000 /* one million */
@@ -1022,20 +854,6 @@ RNG_FileForRNG(const char *fileName)
RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT);
}
-void
-ReadSingleFile(const char *fileName)
-{
- FILE *file;
- unsigned char buffer[BUFSIZ];
-
- file = fopen(fileName, "rb");
- if (file != NULL) {
- while (fread(buffer, 1, sizeof(buffer), file) > 0)
- ;
- fclose(file);
- }
-}
-
#define _POSIX_PTHREAD_SEMANTICS
#include <dirent.h>
@@ -1055,89 +873,6 @@ ReadFileOK(char *dir, char *file)
return S_ISREG(stat_buf.st_mode) ? PR_TRUE : PR_FALSE;
}
-/*
- * read one file out of either /etc or the user's home directory.
- * fileToRead tells which file to read.
- *
- * return 1 if it's time to reset the fileToRead (no more files to read).
- */
-static int
-ReadOneFile(int fileToRead)
-{
- char *dir = "/etc";
- DIR *fd = opendir(dir);
- int resetCount = 0;
- struct dirent *entry;
-#if defined(__sun)
- char firstName[256];
-#else
- char firstName[NAME_MAX + 1];
-#endif
- const char *name = NULL;
- int i;
-
- if (fd == NULL) {
- dir = PR_GetEnvSecure("HOME");
- if (dir) {
- fd = opendir(dir);
- }
- }
- if (fd == NULL) {
- return 1;
- }
-
- firstName[0] = '\0';
- for (i = 0; i <= fileToRead; i++) {
- do {
- /* readdir() isn't guaranteed to be thread safe on every platform;
- * this code assumes the same directory isn't read concurrently.
- * This usage is confirmed safe on Linux, see bug 1254334. */
- entry = readdir(fd);
- } while (entry != NULL && !ReadFileOK(dir, &entry->d_name[0]));
- if (entry == NULL) {
- resetCount = 1; /* read to the end, start again at the beginning */
- if (firstName[0]) {
- /* ran out of entries in the directory, use the first one */
- name = firstName;
- }
- break;
- }
- name = entry->d_name;
- if (i == 0) {
- /* copy the name of the first in case we run out of entries */
- PORT_Assert(PORT_Strlen(name) < sizeof(firstName));
- PORT_Strncpy(firstName, name, sizeof(firstName) - 1);
- firstName[sizeof(firstName) - 1] = '\0';
- }
- }
-
- if (name) {
- char filename[PATH_MAX];
- int count = snprintf(filename, sizeof(filename), "%s/%s", dir, name);
- if (count >= 1) {
- ReadSingleFile(filename);
- }
- }
-
- closedir(fd);
- return resetCount;
-}
-
-/*
- * do something to try to introduce more noise into the 'GetNoise' call
- */
-static void
-rng_systemJitter(void)
-{
- static int fileToRead = 1;
-
- if (ReadOneFile(fileToRead)) {
- fileToRead = 1;
- } else {
- fileToRead++;
- }
-}
-
size_t
RNG_SystemRNG(void *dest, size_t maxLen)
{
@@ -1149,7 +884,8 @@ RNG_SystemRNG(void *dest, size_t maxLen)
file = fopen("/dev/urandom", "r");
if (file == NULL) {
- return rng_systemFromNoise(dest, maxLen);
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ return 0;
}
/* Read from the underlying file descriptor directly to bypass stdio
* buffering and avoid reading more bytes than we need from /dev/urandom.
diff --git a/nss/lib/freebl/unix_urandom.c b/nss/lib/freebl/unix_urandom.c
new file mode 100644
index 0000000..25e6ad9
--- /dev/null
+++ b/nss/lib/freebl/unix_urandom.c
@@ -0,0 +1,50 @@
+/* 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/. */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include "secerr.h"
+#include "secrng.h"
+#include "prprf.h"
+
+void
+RNG_SystemInfoForRNG(void)
+{
+ PRUint8 bytes[SYSTEM_RNG_SEED_COUNT];
+ size_t numBytes = RNG_SystemRNG(bytes, SYSTEM_RNG_SEED_COUNT);
+ if (!numBytes) {
+ /* error is set */
+ return;
+ }
+ RNG_RandomUpdate(bytes, numBytes);
+}
+
+size_t
+RNG_SystemRNG(void *dest, size_t maxLen)
+{
+ int fd;
+ int bytes;
+ size_t fileBytes = 0;
+ unsigned char *buffer = dest;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ return 0;
+ }
+ while (fileBytes < maxLen) {
+ bytes = read(fd, buffer, maxLen - fileBytes);
+ if (bytes <= 0) {
+ break;
+ }
+ fileBytes += bytes;
+ buffer += bytes;
+ }
+ (void)close(fd);
+ if (fileBytes != maxLen) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ return 0;
+ }
+ return fileBytes;
+}