summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/freebl
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl')
-rw-r--r--security/nss/lib/freebl/Makefile39
-rw-r--r--security/nss/lib/freebl/aes-armv8.c1169
-rw-r--r--security/nss/lib/freebl/aes-armv8.h103
-rw-r--r--security/nss/lib/freebl/aes-x86.c12
-rw-r--r--security/nss/lib/freebl/aeskeywrap.c3
-rw-r--r--security/nss/lib/freebl/altivec-types.h23
-rw-r--r--security/nss/lib/freebl/blapi.h5
-rw-r--r--security/nss/lib/freebl/blapii.h1
-rw-r--r--security/nss/lib/freebl/blinit.c147
-rw-r--r--security/nss/lib/freebl/chacha20poly1305.c33
-rw-r--r--security/nss/lib/freebl/cmac.c322
-rw-r--r--security/nss/lib/freebl/cmac.h47
-rw-r--r--security/nss/lib/freebl/config.mk5
-rw-r--r--security/nss/lib/freebl/crypto_primitives.c2
-rw-r--r--security/nss/lib/freebl/crypto_primitives.h17
-rw-r--r--security/nss/lib/freebl/ctr.c13
-rw-r--r--security/nss/lib/freebl/drbg.c99
-rw-r--r--security/nss/lib/freebl/ec.c2
-rw-r--r--security/nss/lib/freebl/ecl/curve25519_32.c1447
-rw-r--r--security/nss/lib/freebl/exports.gyp1
-rw-r--r--security/nss/lib/freebl/fipsfreebl.c344
-rw-r--r--security/nss/lib/freebl/freebl.gyp175
-rw-r--r--security/nss/lib/freebl/freebl_base.gypi3
-rw-r--r--security/nss/lib/freebl/gcm-aarch64.c96
-rw-r--r--security/nss/lib/freebl/gcm-ppc.c109
-rw-r--r--security/nss/lib/freebl/gcm.c25
-rw-r--r--security/nss/lib/freebl/gcm.h30
-rw-r--r--security/nss/lib/freebl/intel-aes.h38
-rw-r--r--security/nss/lib/freebl/intel-gcm-wrap.c12
-rw-r--r--security/nss/lib/freebl/ldvector.c15
-rw-r--r--security/nss/lib/freebl/loader.c61
-rw-r--r--security/nss/lib/freebl/loader.h22
-rw-r--r--security/nss/lib/freebl/manifest.mn3
-rw-r--r--security/nss/lib/freebl/mpi/README1
-rw-r--r--security/nss/lib/freebl/mpi/mpcpucache.c2
-rw-r--r--security/nss/lib/freebl/mpi/mpi.c69
-rw-r--r--security/nss/lib/freebl/mpi/mpi.h11
-rw-r--r--security/nss/lib/freebl/pqg.c129
-rw-r--r--security/nss/lib/freebl/rijndael.c40
-rw-r--r--security/nss/lib/freebl/rijndael.h2
-rw-r--r--security/nss/lib/freebl/rsapkcs.c3
-rw-r--r--security/nss/lib/freebl/seed.c33
-rw-r--r--security/nss/lib/freebl/sha_fast.h2
-rw-r--r--security/nss/lib/freebl/unix_urandom.c2
-rw-r--r--security/nss/lib/freebl/verified/FStar.c2
-rw-r--r--security/nss/lib/freebl/verified/FStar.h2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Chacha20.c2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Chacha20.h2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Curve25519.c2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Curve25519.h2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Poly1305_32.c2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Poly1305_32.h2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Poly1305_64.c2
-rw-r--r--security/nss/lib/freebl/verified/Hacl_Poly1305_64.h2
-rw-r--r--security/nss/lib/freebl/verified/kremlib.h2
-rw-r--r--security/nss/lib/freebl/verified/kremlib_base.h2
-rw-r--r--security/nss/lib/freebl/verified/vec128.h2
59 files changed, 4207 insertions, 540 deletions
diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile
index bff11c7c8..98a7c5d5c 100644
--- a/security/nss/lib/freebl/Makefile
+++ b/security/nss/lib/freebl/Makefile
@@ -119,6 +119,26 @@ else
DEFINES += -DNSS_X86
endif
endif
+ifeq ($(CPU_ARCH),aarch64)
+ DEFINES += -DUSE_HW_AES
+ EXTRA_SRCS += aes-armv8.c gcm-aarch64.c
+endif
+ifeq ($(CPU_ARCH),arm)
+ ifdef CC_IS_CLANG
+ DEFINES += -DUSE_HW_AES
+ EXTRA_SRCS += aes-armv8.c
+ else ifeq (1,$(CC_IS_GCC))
+ # Old compiler doesn't support ARM AES.
+ ifneq (,$(filter 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
+ DEFINES += -DUSE_HW_AES
+ EXTRA_SRCS += aes-armv8.c
+ endif
+ ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
+ DEFINES += -DUSE_HW_AES
+ EXTRA_SRCS += aes-armv8.c
+ endif
+ endif
+endif
ifeq ($(OS_TARGET),OSF1)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
@@ -243,6 +263,7 @@ ifeq ($(CPU_ARCH),arm)
MPI_SRCS += mpi_arm.c
endif
ifeq ($(CPU_ARCH),ppc)
+ EXTRA_SRCS += gcm-ppc.c
ifdef USE_64
DEFINES += -DNSS_NO_INIT_SUPPORT
endif # USE_64
@@ -493,6 +514,9 @@ endif # Solaris for non-sparc family CPUs
endif # target == SunO
ifdef USE_64
+# no __int128 at least up to lcc 1.23 (pretending to be gcc5)
+# NB: CC_NAME is not defined here
+ifneq ($(shell $(CC) -? 2>&1 >/dev/null </dev/null | sed -e 's/:.*//;1q'),lcc)
ifdef CC_IS_CLANG
HAVE_INT128_SUPPORT = 1
DEFINES += -DHAVE_INT128_SUPPORT
@@ -506,7 +530,8 @@ ifdef USE_64
DEFINES += -DHAVE_INT128_SUPPORT
endif
endif
-endif
+endif # lcc
+endif # USE_64
ifndef HAVE_INT128_SUPPORT
DEFINES += -DKRML_NOUINT128
@@ -753,3 +778,15 @@ ifdef INTEL_GCM_CLANG_CL
#
$(OBJDIR)/$(PROG_PREFIX)intel-gcm-wrap$(OBJ_SUFFIX): CFLAGS += -mssse3
endif
+
+ifeq ($(CPU_ARCH),arm)
+$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8
+endif
+ifeq ($(CPU_ARCH),aarch64)
+$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
+$(OBJDIR)/$(PROG_PREFIX)gcm-aarch64$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
+endif
+
+ifeq ($(CPU_ARCH),ppc)
+$(OBJDIR)/$(PROG_PREFIX)gcm-ppc$(OBJ_SUFFIX): CFLAGS += -mcrypto -maltivec
+endif
diff --git a/security/nss/lib/freebl/aes-armv8.c b/security/nss/lib/freebl/aes-armv8.c
new file mode 100644
index 000000000..8213272f5
--- /dev/null
+++ b/security/nss/lib/freebl/aes-armv8.c
@@ -0,0 +1,1169 @@
+/* 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 "secerr.h"
+#include "rijndael.h"
+
+#if ((defined(__clang__) || \
+ (defined(__GNUC__) && defined(__GNUC_MINOR__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)))) && \
+ (defined(__ARM_NEON) || defined(__ARM_NEON__)))
+
+#ifndef __ARM_FEATURE_CRYPTO
+#error "Compiler option is invalid"
+#endif
+
+#include <arm_neon.h>
+
+SECStatus
+arm_aes_encrypt_ecb_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ /* AddRoundKey */
+ state = veorq_u8(state, key11);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_ecb_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (inputLen == 0) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_encrypt_cbc_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11;
+ uint8x16_t iv;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ state = veorq_u8(state, iv);
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ /* AddRoundKey */
+ state = veorq_u8(state, key11);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ iv = state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_cbc_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t iv;
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+
+ while (inputLen > 0) {
+ uint8x16_t state, old_state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ old_state = state;
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+ state = veorq_u8(state, iv);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+
+ iv = old_state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_encrypt_ecb_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13;
+ PRUint8 *key = (PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key11);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key12);
+ /* AddRoundKey */
+ state = veorq_u8(state, key13);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_ecb_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key13);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key12);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_encrypt_cbc_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13;
+ uint8x16_t iv;
+ PRUint8 *key = (PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ state = veorq_u8(state, iv);
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key11);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key12);
+ state = veorq_u8(state, key13);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ iv = state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_cbc_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t iv;
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+
+ while (inputLen > 0) {
+ uint8x16_t state, old_state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ old_state = state;
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key13);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key12);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+ state = veorq_u8(state, iv);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+
+ iv = old_state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_encrypt_ecb_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13, key14, key15;
+ PRUint8 *key = (PRUint8 *)cx->k.expandedKey;
+
+ if (inputLen == 0) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+ key14 = vld1q_u8(key + 208);
+ key15 = vld1q_u8(key + 224);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key11);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key12);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key13);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key14);
+ /* AddRoundKey */
+ state = veorq_u8(state, key15);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_ecb_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13, key14, key15;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+ key14 = vld1q_u8(key + 208);
+ key15 = vld1q_u8(key + 224);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key15);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key14);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key13);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key12);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_encrypt_cbc_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13, key14, key15;
+ uint8x16_t iv;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+ key14 = vld1q_u8(key + 208);
+ key15 = vld1q_u8(key + 224);
+
+ while (inputLen > 0) {
+ uint8x16_t state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ input += 16;
+ inputLen -= 16;
+
+ state = veorq_u8(state, iv);
+
+ /* Rounds */
+ state = vaeseq_u8(state, key1);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key2);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key3);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key4);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key5);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key6);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key7);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key8);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key9);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key10);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key11);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key12);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key13);
+ state = vaesmcq_u8(state);
+ state = vaeseq_u8(state, key14);
+ /* AddRoundKey */
+ state = veorq_u8(state, key15);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+ iv = state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+SECStatus
+arm_aes_decrypt_cbc_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize)
+{
+#if !defined(HAVE_UNALIGNED_ACCESS)
+ pre_align unsigned char buf[16] post_align;
+#endif
+ uint8x16_t iv;
+ uint8x16_t key1, key2, key3, key4, key5, key6, key7, key8, key9, key10;
+ uint8x16_t key11, key12, key13, key14, key15;
+ const PRUint8 *key = (const PRUint8 *)cx->k.expandedKey;
+
+ if (!inputLen) {
+ return SECSuccess;
+ }
+
+ /* iv */
+ iv = vld1q_u8(cx->iv);
+
+ /* expanedKey */
+ key1 = vld1q_u8(key);
+ key2 = vld1q_u8(key + 16);
+ key3 = vld1q_u8(key + 32);
+ key4 = vld1q_u8(key + 48);
+ key5 = vld1q_u8(key + 64);
+ key6 = vld1q_u8(key + 80);
+ key7 = vld1q_u8(key + 96);
+ key8 = vld1q_u8(key + 112);
+ key9 = vld1q_u8(key + 128);
+ key10 = vld1q_u8(key + 144);
+ key11 = vld1q_u8(key + 160);
+ key12 = vld1q_u8(key + 176);
+ key13 = vld1q_u8(key + 192);
+ key14 = vld1q_u8(key + 208);
+ key15 = vld1q_u8(key + 224);
+
+ while (inputLen > 0) {
+ uint8x16_t state, old_state;
+#if defined(HAVE_UNALIGNED_ACCESS)
+ state = vld1q_u8(input);
+#else
+ if ((uintptr_t)input & 0x7) {
+ memcpy(buf, input, 16);
+ state = vld1q_u8(__builtin_assume_aligned(buf, 16));
+ } else {
+ state = vld1q_u8(__builtin_assume_aligned(input, 8));
+ }
+#endif
+ old_state = state;
+ input += 16;
+ inputLen -= 16;
+
+ /* Rounds */
+ state = vaesdq_u8(state, key15);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key14);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key13);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key12);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key11);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key10);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key9);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key8);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key7);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key6);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key5);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key4);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key3);
+ state = vaesimcq_u8(state);
+ state = vaesdq_u8(state, key2);
+ /* AddRoundKey */
+ state = veorq_u8(state, key1);
+
+ state = veorq_u8(state, iv);
+
+#if defined(HAVE_UNALIGNED_ACCESS)
+ vst1q_u8(output, state);
+#else
+ if ((uintptr_t)output & 0x7) {
+ vst1q_u8(__builtin_assume_aligned(buf, 16), state);
+ memcpy(output, buf, 16);
+ } else {
+ vst1q_u8(__builtin_assume_aligned(output, 8), state);
+ }
+#endif
+ output += 16;
+
+ iv = old_state;
+ }
+ vst1q_u8(cx->iv, iv);
+
+ return SECSuccess;
+}
+
+#endif
diff --git a/security/nss/lib/freebl/aes-armv8.h b/security/nss/lib/freebl/aes-armv8.h
new file mode 100644
index 000000000..b0ef1c870
--- /dev/null
+++ b/security/nss/lib/freebl/aes-armv8.h
@@ -0,0 +1,103 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+SECStatus arm_aes_encrypt_ecb_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_ecb_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_encrypt_cbc_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_cbc_128(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_encrypt_ecb_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_ecb_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_encrypt_cbc_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_cbc_192(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_encrypt_ecb_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_ecb_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_encrypt_cbc_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+SECStatus arm_aes_decrypt_cbc_256(AESContext *cx, unsigned char *output,
+ unsigned int *outputLen,
+ unsigned int maxOutputLen,
+ const unsigned char *input,
+ unsigned int inputLen,
+ unsigned int blocksize);
+
+#define native_aes_ecb_worker(encrypt, keysize) \
+ ((encrypt) \
+ ? ((keysize) == 16 ? arm_aes_encrypt_ecb_128 \
+ : (keysize) == 24 ? arm_aes_encrypt_ecb_192 \
+ : arm_aes_encrypt_ecb_256) \
+ : ((keysize) == 16 ? arm_aes_decrypt_ecb_128 \
+ : (keysize) == 24 ? arm_aes_decrypt_ecb_192 \
+ : arm_aes_decrypt_ecb_256))
+
+#define native_aes_cbc_worker(encrypt, keysize) \
+ ((encrypt) \
+ ? ((keysize) == 16 ? arm_aes_encrypt_cbc_128 \
+ : (keysize) == 24 ? arm_aes_encrypt_cbc_192 \
+ : arm_aes_encrypt_cbc_256) \
+ : ((keysize) == 16 ? arm_aes_decrypt_cbc_128 \
+ : (keysize) == 24 ? arm_aes_decrypt_cbc_192 \
+ : arm_aes_decrypt_cbc_256))
+
+#define native_aes_init(encrypt, keysize) \
+ do { \
+ if (encrypt) { \
+ rijndael_key_expansion(cx, key, Nk); \
+ } else { \
+ rijndael_invkey_expansion(cx, key, Nk); \
+ } \
+ } while (0)
diff --git a/security/nss/lib/freebl/aes-x86.c b/security/nss/lib/freebl/aes-x86.c
index 830b4782f..edd0b5125 100644
--- a/security/nss/lib/freebl/aes-x86.c
+++ b/security/nss/lib/freebl/aes-x86.c
@@ -21,7 +21,7 @@
static void
native_key_expansion128(AESContext *cx, const unsigned char *key)
{
- __m128i *keySchedule = cx->keySchedule;
+ __m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
@@ -61,7 +61,7 @@ native_key_expansion128(AESContext *cx, const unsigned char *key)
static void
native_key_expansion192(AESContext *cx, const unsigned char *key)
{
- __m128i *keySchedule = cx->keySchedule;
+ __m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
pre_align __m128i tmp3 post_align;
@@ -96,7 +96,7 @@ native_key_expansion192(AESContext *cx, const unsigned char *key)
static void
native_key_expansion256(AESContext *cx, const unsigned char *key)
{
- __m128i *keySchedule = cx->keySchedule;
+ __m128i *keySchedule = cx->k.keySchedule;
pre_align __m128i tmp_key post_align;
pre_align __m128i tmp1 post_align;
pre_align __m128i tmp2 post_align;
@@ -148,10 +148,10 @@ rijndael_native_encryptBlock(AESContext *cx,
{
int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
- m = _mm_xor_si128(m, cx->keySchedule[0]);
+ m = _mm_xor_si128(m, cx->k.keySchedule[0]);
for (i = 1; i < cx->Nr; ++i) {
- m = _mm_aesenc_si128(m, cx->keySchedule[i]);
+ m = _mm_aesenc_si128(m, cx->k.keySchedule[i]);
}
- m = _mm_aesenclast_si128(m, cx->keySchedule[cx->Nr]);
+ m = _mm_aesenclast_si128(m, cx->k.keySchedule[cx->Nr]);
_mm_storeu_si128((__m128i *)output, m);
}
diff --git a/security/nss/lib/freebl/aeskeywrap.c b/security/nss/lib/freebl/aeskeywrap.c
index ee909dbd0..3d2c9e448 100644
--- a/security/nss/lib/freebl/aeskeywrap.c
+++ b/security/nss/lib/freebl/aeskeywrap.c
@@ -225,7 +225,8 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
#define A B[0]
/* Check args */
- if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
+ if (inputLen < 2 * AES_KEY_WRAP_BLOCK_SIZE ||
+ 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return s;
}
diff --git a/security/nss/lib/freebl/altivec-types.h b/security/nss/lib/freebl/altivec-types.h
new file mode 100644
index 000000000..807a44db4
--- /dev/null
+++ b/security/nss/lib/freebl/altivec-types.h
@@ -0,0 +1,23 @@
+/*
+ * altivec-types.h - shorter vector typedefs
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _ALTIVEC_TYPES_H_
+#define _ALTIVEC_TYPES_H_ 1
+
+#include <altivec.h>
+
+typedef __vector unsigned char vec_u8;
+typedef __vector signed char vec_s8;
+typedef __vector unsigned short vec_u16;
+typedef __vector signed short vec_s16;
+typedef __vector unsigned int vec_u32;
+typedef __vector signed int vec_s32;
+typedef __vector unsigned long long vec_u64;
+typedef __vector signed long long vec_s64;
+typedef __vector float vec_f;
+
+#endif
diff --git a/security/nss/lib/freebl/blapi.h b/security/nss/lib/freebl/blapi.h
index ca2149972..3b404992b 100644
--- a/security/nss/lib/freebl/blapi.h
+++ b/security/nss/lib/freebl/blapi.h
@@ -10,6 +10,7 @@
#include "blapit.h"
#include "hasht.h"
+#include "cmac.h"
#include "alghmac.h"
SEC_BEGIN_PROTOS
@@ -1013,6 +1014,10 @@ extern SECStatus ChaCha20Poly1305_Open(
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen);
+extern SECStatus ChaCha20_Xor(
+ unsigned char *output, const unsigned char *block, unsigned int len,
+ const unsigned char *k, const unsigned char *nonce, PRUint32 ctr);
+
/******************************************/
/*
** MD5 secure hash function
diff --git a/security/nss/lib/freebl/blapii.h b/security/nss/lib/freebl/blapii.h
index 743a1168b..006c26977 100644
--- a/security/nss/lib/freebl/blapii.h
+++ b/security/nss/lib/freebl/blapii.h
@@ -86,5 +86,6 @@ PRBool arm_aes_support();
PRBool arm_pmull_support();
PRBool arm_sha1_support();
PRBool arm_sha2_support();
+PRBool ppc_crypto_support();
#endif /* _BLAPII_H_ */
diff --git a/security/nss/lib/freebl/blinit.c b/security/nss/lib/freebl/blinit.c
index f369e62e7..959109b60 100644
--- a/security/nss/lib/freebl/blinit.c
+++ b/security/nss/lib/freebl/blinit.c
@@ -29,6 +29,7 @@ static PRBool arm_aes_support_ = PR_FALSE;
static PRBool arm_sha1_support_ = PR_FALSE;
static PRBool arm_sha2_support_ = PR_FALSE;
static PRBool arm_pmull_support_ = PR_FALSE;
+static PRBool ppc_crypto_support_ = PR_FALSE;
#ifdef NSS_X86_OR_X64
/*
@@ -92,23 +93,32 @@ CheckX86CPUSupport()
#endif /* NSS_X86_OR_X64 */
/* clang-format off */
-#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
+#if defined(__aarch64__) || defined(__arm__)
#ifndef __has_include
#define __has_include(x) 0
#endif
#if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \
defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)
+/* This might be conflict with host compiler */
+#if !defined(__ANDROID__)
#include <sys/auxv.h>
+#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else
static unsigned long (*getauxval)(unsigned long) = NULL;
-#define AT_HWCAP2 0
-#define AT_HWCAP 0
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/
-#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */
+
+#ifndef AT_HWCAP2
+#define AT_HWCAP2 26
+#endif
+#ifndef AT_HWCAP
+#define AT_HWCAP 16
+#endif
+
+#endif /* defined(__aarch64__) || defined(__arm__) */
/* clang-format on */
-#if defined(__aarch64__) && !defined(__ANDROID__)
+#if defined(__aarch64__)
// Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES
#define HWCAP_AES (1 << 3)
@@ -128,19 +138,20 @@ CheckARMSupport()
{
char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
+ char *disable_pmull = PR_GetEnvSecure("NSS_DISABLE_PMULL");
if (getauxval) {
long hwcaps = getauxval(AT_HWCAP);
arm_aes_support_ = hwcaps & HWCAP_AES && disable_hw_aes == NULL;
- arm_pmull_support_ = hwcaps & HWCAP_PMULL;
+ arm_pmull_support_ = hwcaps & HWCAP_PMULL && disable_pmull == NULL;
arm_sha1_support_ = hwcaps & HWCAP_SHA1;
arm_sha2_support_ = hwcaps & HWCAP_SHA2;
}
/* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL;
}
-#endif /* defined(__aarch64__) && !defined(__ANDROID__) */
+#endif /* defined(__aarch64__) */
-#if defined(__arm__) && !defined(__ANDROID__)
+#if defined(__arm__)
// Defines from hwcap.h in Linux kernel - ARM
/*
* HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
@@ -165,23 +176,105 @@ CheckARMSupport()
#define HWCAP2_SHA2 (1 << 3)
#endif
+PRBool
+GetNeonSupport()
+{
+ char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
+ if (disable_arm_neon) {
+ return PR_FALSE;
+ }
+#if defined(__ARM_NEON) || defined(__ARM_NEON__)
+ // Compiler generates NEON instruction as default option.
+ // If no getauxval, compiler generate NEON instruction by default,
+ // we should allow NOEN support.
+ return PR_TRUE;
+#elif !defined(__ANDROID__)
+ // Android's cpu-features.c detects features by the following logic
+ //
+ // - Call getauxval(AT_HWCAP)
+ // - Parse /proc/self/auxv if getauxval is nothing or returns 0
+ // - Parse /proc/cpuinfo if both cannot detect features
+ //
+ // But we don't use it for Android since Android document
+ // (https://developer.android.com/ndk/guides/cpu-features) says
+ // one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator)
+ // are mistaken for IDIV.
+ if (getauxval) {
+ return (getauxval(AT_HWCAP) & HWCAP_NEON);
+ }
+#endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */
+ return PR_FALSE;
+}
+
+#ifdef __linux__
+static long
+ReadCPUInfoForHWCAP2()
+{
+ FILE *cpuinfo;
+ char buf[512];
+ char *p;
+ long hwcap2 = 0;
+
+ cpuinfo = fopen("/proc/cpuinfo", "r");
+ if (!cpuinfo) {
+ return 0;
+ }
+ while (fgets(buf, 511, cpuinfo)) {
+ if (!memcmp(buf, "Features", 8)) {
+ p = strstr(buf, " aes");
+ if (p && (p[4] == ' ' || p[4] == '\n')) {
+ hwcap2 |= HWCAP2_AES;
+ }
+ p = strstr(buf, " sha1");
+ if (p && (p[5] == ' ' || p[5] == '\n')) {
+ hwcap2 |= HWCAP2_SHA1;
+ }
+ p = strstr(buf, " sha2");
+ if (p && (p[5] == ' ' || p[5] == '\n')) {
+ hwcap2 |= HWCAP2_SHA2;
+ }
+ p = strstr(buf, " pmull");
+ if (p && (p[6] == ' ' || p[6] == '\n')) {
+ hwcap2 |= HWCAP2_PMULL;
+ }
+ break;
+ }
+ }
+
+ fclose(cpuinfo);
+ return hwcap2;
+}
+#endif /* __linux__ */
+
void
CheckARMSupport()
{
- char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON");
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
if (getauxval) {
+ // Android's cpu-features.c uses AT_HWCAP2 for newer features.
+ // AT_HWCAP2 is implemented on newer devices / kernel, so we can trust
+ // it since cpu-features.c doesn't have workaround / fallback.
+ // Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If
+ // AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
+ // returns 0.
long hwcaps = getauxval(AT_HWCAP2);
+#ifdef __linux__
+ if (!hwcaps) {
+ // Some ARMv8 devices may not implement AT_HWCAP2. So we also
+ // read /proc/cpuinfo if AT_HWCAP2 is 0.
+ hwcaps = ReadCPUInfoForHWCAP2();
+ }
+#endif
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
arm_sha2_support_ = hwcaps & HWCAP2_SHA2;
- arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL;
}
+ arm_neon_support_ = GetNeonSupport();
}
-#endif /* defined(__arm__) && !defined(__ANDROID__) */
+#endif /* defined(__arm__) */
-// Enable when Firefox can use it.
+// Enable when Firefox can use it for Android API 16 and 17.
// #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__))
// #include <cpu-features.h>
// void
@@ -256,14 +349,42 @@ arm_sha2_support()
{
return arm_sha2_support_;
}
+PRBool
+ppc_crypto_support()
+{
+ return ppc_crypto_support_;
+}
+
+#if defined(__powerpc__)
+
+#include <sys/auxv.h>
+
+// Defines from cputable.h in Linux kernel - PPC, letting us build on older kernels
+#ifndef PPC_FEATURE2_VEC_CRYPTO
+#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
+#endif
+
+static void
+CheckPPCSupport()
+{
+ char *disable_hw_crypto = PR_GetEnvSecure("NSS_DISABLE_PPC_GHASH");
+
+ long hwcaps = getauxval(AT_HWCAP2);
+
+ ppc_crypto_support_ = hwcaps & PPC_FEATURE2_VEC_CRYPTO && disable_hw_crypto == NULL;
+}
+
+#endif /* __powerpc__ */
static PRStatus
FreeblInit(void)
{
#ifdef NSS_X86_OR_X64
CheckX86CPUSupport();
-#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__)
+#elif (defined(__aarch64__) || defined(__arm__))
CheckARMSupport();
+#elif (defined(__powerpc__))
+ CheckPPCSupport();
#endif
return PR_SUCCESS;
}
diff --git a/security/nss/lib/freebl/chacha20poly1305.c b/security/nss/lib/freebl/chacha20poly1305.c
index 8fdaf3fec..63359a22a 100644
--- a/security/nss/lib/freebl/chacha20poly1305.c
+++ b/security/nss/lib/freebl/chacha20poly1305.c
@@ -157,6 +157,7 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit)
#endif
}
+#ifndef NSS_DISABLE_CHACHAPOLY
void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr)
@@ -167,6 +168,25 @@ ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr);
}
}
+#endif /* NSS_DISABLE_CHACHAPOLY */
+
+SECStatus
+ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
+ const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
+{
+#ifdef NSS_DISABLE_CHACHAPOLY
+ return SECFailure;
+#else
+ // ChaCha has a 64 octet block, with a 32-bit block counter.
+ if (sizeof(len) > 4 && len >= (1ULL << (6 + 32))) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ ChaCha20Xor(output, (uint8_t *)block, len, (uint8_t *)k,
+ (uint8_t *)nonce, ctr);
+ return SECSuccess;
+#endif
+}
SECStatus
ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
@@ -185,8 +205,12 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
- *outputLen = inputLen + ctx->tagLen;
- if (maxOutputLen < *outputLen) {
+ // ChaCha has a 64 octet block, with a 32-bit block counter.
+ if (sizeof(inputLen) > 4 && inputLen >= (1ULL << (6 + 32))) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ return SECFailure;
+ }
+ if (maxOutputLen < inputLen + ctx->tagLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@@ -202,6 +226,7 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
Poly1305Do(tag, ad, adLen, output, inputLen, block);
PORT_Memcpy(output + inputLen, tag, ctx->tagLen);
+ *outputLen = inputLen + ctx->tagLen;
return SECSuccess;
#endif
}
@@ -229,8 +254,7 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
return SECFailure;
}
ciphertextLen = inputLen - ctx->tagLen;
- *outputLen = ciphertextLen;
- if (maxOutputLen < *outputLen) {
+ if (maxOutputLen < ciphertextLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@@ -254,6 +278,7 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
ChaCha20Xor(output, (uint8_t *)input, ciphertextLen, (uint8_t *)ctx->key,
(uint8_t *)nonce, 1);
+ *outputLen = ciphertextLen;
return SECSuccess;
#endif
}
diff --git a/security/nss/lib/freebl/cmac.c b/security/nss/lib/freebl/cmac.c
new file mode 100644
index 000000000..73237c03a
--- /dev/null
+++ b/security/nss/lib/freebl/cmac.c
@@ -0,0 +1,322 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+
+#include "rijndael.h"
+#include "blapi.h"
+#include "cmac.h"
+#include "secerr.h"
+#include "nspr.h"
+
+struct CMACContextStr {
+ /* Information about the block cipher to use internally. The cipher should
+ * be placed in ECB mode so that we can use it to directly encrypt blocks.
+ *
+ *
+ * To add a new cipher, add an entry to CMACCipher, update CMAC_Init,
+ * cmac_Encrypt, and CMAC_Destroy methods to handle the new cipher, and
+ * add a new Context pointer to the cipher union with the correct type. */
+ CMACCipher cipherType;
+ union {
+ AESContext aes;
+ } cipher;
+ int blockSize;
+
+ /* Internal keys which are conditionally used by the algorithm. Derived
+ * from encrypting the NULL block. We leave the storing of (and the
+ * cleanup of) the CMAC key to the underlying block cipher. */
+ unsigned char k1[MAX_BLOCK_SIZE];
+ unsigned char k2[MAX_BLOCK_SIZE];
+
+ /* When Update is called with data which isn't a multiple of the block
+ * size, we need a place to put it. HMAC handles this by passing it to
+ * the underlying hash function right away; we can't do that as the
+ * contract on the cipher object is different. */
+ unsigned int partialIndex;
+ unsigned char partialBlock[MAX_BLOCK_SIZE];
+
+ /* Last encrypted block. This gets xor-ed with partialBlock prior to
+ * encrypting it. NIST defines this to be the empty string to begin. */
+ unsigned char lastBlock[MAX_BLOCK_SIZE];
+};
+
+static void
+cmac_ShiftLeftOne(unsigned char *out, const unsigned char *in, int length)
+{
+ int i = 0;
+ for (; i < length - 1; i++) {
+ out[i] = in[i] << 1;
+ out[i] |= in[i + 1] >> 7;
+ }
+ out[i] = in[i] << 1;
+}
+
+static SECStatus
+cmac_Encrypt(CMACContext *ctx, unsigned char *output,
+ const unsigned char *input,
+ unsigned int inputLen)
+{
+ if (ctx->cipherType == CMAC_AES) {
+ unsigned int tmpOutputLen;
+ SECStatus rv = AES_Encrypt(&ctx->cipher.aes, output, &tmpOutputLen,
+ ctx->blockSize, input, inputLen);
+
+ /* Assumption: AES_Encrypt (when in ECB mode) always returns an
+ * output of length equal to blockSize (what was pass as the value
+ * of the maxOutputLen parameter). */
+ PORT_Assert(tmpOutputLen == ctx->blockSize);
+ return rv;
+ }
+
+ return SECFailure;
+}
+
+/* NIST SP.800-38B, 6.1 Subkey Generation */
+static SECStatus
+cmac_GenerateSubkeys(CMACContext *ctx)
+{
+ unsigned char null_block[MAX_BLOCK_SIZE] = { 0 };
+ unsigned char L[MAX_BLOCK_SIZE];
+ unsigned char v;
+ unsigned char i;
+
+ /* Step 1: L = AES(key, null_block) */
+ if (cmac_Encrypt(ctx, L, null_block, ctx->blockSize) != SECSuccess) {
+ return SECFailure;
+ }
+
+ /* In the following, some effort has been made to be constant time. Rather
+ * than conditioning on the value of the MSB (of L or K1), we use the loop
+ * to build a mask for the conditional constant. */
+
+ /* Step 2: If MSB(L) = 0, K1 = L << 1. Else, K1 = (L << 1) ^ R_b. */
+ cmac_ShiftLeftOne(ctx->k1, L, ctx->blockSize);
+ v = L[0] >> 7;
+ for (i = 1; i <= 7; i <<= 1) {
+ v |= (v << i);
+ }
+ ctx->k1[ctx->blockSize - 1] ^= (0x87 & v);
+
+ /* Step 3: If MSB(K1) = 0, K2 = K1 << 1. Else, K2 = (K1 <, 1) ^ R_b. */
+ cmac_ShiftLeftOne(ctx->k2, ctx->k1, ctx->blockSize);
+ v = ctx->k1[0] >> 7;
+ for (i = 1; i <= 7; i <<= 1) {
+ v |= (v << i);
+ }
+ ctx->k2[ctx->blockSize - 1] ^= (0x87 & v);
+
+ /* Any intermediate value in the computation of the subkey shall be
+ * secret. */
+ PORT_Memset(null_block, 0, MAX_BLOCK_SIZE);
+ PORT_Memset(L, 0, MAX_BLOCK_SIZE);
+
+ /* Step 4: Return the values. */
+ return SECSuccess;
+}
+
+/* NIST SP.800-38B, 6.2 MAC Generation step 6 */
+static SECStatus
+cmac_UpdateState(CMACContext *ctx)
+{
+ if (ctx == NULL || ctx->partialIndex != ctx->blockSize) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* Step 6: C_i = CIPHER(key, C_{i-1} ^ M_i) for 1 <= i <= n, and
+ * C_0 is defined as the empty string. */
+
+ for (unsigned int index = 0; index < ctx->blockSize; index++) {
+ ctx->partialBlock[index] ^= ctx->lastBlock[index];
+ }
+
+ return cmac_Encrypt(ctx, ctx->lastBlock, ctx->partialBlock, ctx->blockSize);
+}
+
+SECStatus
+CMAC_Init(CMACContext *ctx, CMACCipher type,
+ const unsigned char *key, unsigned int key_len)
+{
+ if (ctx == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ /* We only currently support AES-CMAC. */
+ if (type != CMAC_AES) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ PORT_Memset(ctx, 0, sizeof(*ctx));
+
+ ctx->blockSize = AES_BLOCK_SIZE;
+ ctx->cipherType = CMAC_AES;
+ if (AES_InitContext(&ctx->cipher.aes, key, key_len, NULL, NSS_AES, 1,
+ ctx->blockSize) != SECSuccess) {
+ return SECFailure;
+ }
+
+ return CMAC_Begin(ctx);
+}
+
+CMACContext *
+CMAC_Create(CMACCipher type, const unsigned char *key,
+ unsigned int key_len)
+{
+ CMACContext *result = PORT_New(CMACContext);
+
+ if (CMAC_Init(result, type, key, key_len) != SECSuccess) {
+ CMAC_Destroy(result, PR_TRUE);
+ return NULL;
+ }
+
+ return result;
+}
+
+SECStatus
+CMAC_Begin(CMACContext *ctx)
+{
+ if (ctx == NULL) {
+ return SECFailure;
+ }
+
+ /* Ensure that our blockSize is less than the maximum. When this fails,
+ * a cipher with a larger block size was added and MAX_BLOCK_SIZE needs
+ * to be updated accordingly. */
+ PORT_Assert(ctx->blockSize <= MAX_BLOCK_SIZE);
+
+ if (cmac_GenerateSubkeys(ctx) != SECSuccess) {
+ return SECFailure;
+ }
+
+ /* Set the index to write partial blocks at to zero. This saves us from
+ * having to clear ctx->partialBlock. */
+ ctx->partialIndex = 0;
+
+ /* Step 5: Let C_0 = 0^b. */
+ PORT_Memset(ctx->lastBlock, 0, ctx->blockSize);
+
+ return SECSuccess;
+}
+
+/* NIST SP.800-38B, 6.2 MAC Generation */
+SECStatus
+CMAC_Update(CMACContext *ctx, const unsigned char *data,
+ unsigned int data_len)
+{
+ int data_index = 0;
+ if (ctx == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (data == NULL || data_len == 0) {
+ return SECSuccess;
+ }
+
+ /* Copy as many bytes from data into ctx->partialBlock as we can, up to
+ * the maximum of the remaining data and the remaining space in
+ * ctx->partialBlock.
+ *
+ * Note that we swap the order (encrypt *then* copy) because the last
+ * block is different from the rest. If we end on an even multiple of
+ * the block size, we have to be able to XOR it with K1. But we won't know
+ * that it is the last until CMAC_Finish is called (and by then, CMAC_Update
+ * has already returned). */
+ while (data_index < data_len) {
+ if (ctx->partialIndex == ctx->blockSize) {
+ if (cmac_UpdateState(ctx) != SECSuccess) {
+ return SECFailure;
+ }
+
+ ctx->partialIndex = 0;
+ }
+
+ unsigned int copy_len = data_len - data_index;
+ if (copy_len > (ctx->blockSize - ctx->partialIndex)) {
+ copy_len = ctx->blockSize - ctx->partialIndex;
+ }
+
+ PORT_Memcpy(ctx->partialBlock + ctx->partialIndex, data + data_index, copy_len);
+ data_index += copy_len;
+ ctx->partialIndex += copy_len;
+ }
+
+ return SECSuccess;
+}
+
+/* NIST SP.800-38B, 6.2 MAC Generation */
+SECStatus
+CMAC_Finish(CMACContext *ctx, unsigned char *result,
+ unsigned int *result_len,
+ unsigned int max_result_len)
+{
+ if (ctx == NULL || result == NULL || max_result_len == 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (max_result_len > ctx->blockSize) {
+ /* This is a weird situation. The PKCS #11 soft tokencode passes
+ * sizeof(result) here, which is hard-coded as SFTK_MAX_MAC_LENGTH.
+ * This later gets truncated to min(SFTK_MAX_MAC_LENGTH, requested). */
+ max_result_len = ctx->blockSize;
+ }
+
+ /* Step 4: If M_n* is a complete block, M_n = K1 ^ M_n*. Else,
+ * M_n = K2 ^ (M_n* || 10^j). */
+ if (ctx->partialIndex == ctx->blockSize) {
+ /* XOR in K1. */
+ for (unsigned int index = 0; index < ctx->blockSize; index++) {
+ ctx->partialBlock[index] ^= ctx->k1[index];
+ }
+ } else {
+ /* Use 10* padding on the partial block. */
+ ctx->partialBlock[ctx->partialIndex++] = 0x80;
+ PORT_Memset(ctx->partialBlock + ctx->partialIndex, 0,
+ ctx->blockSize - ctx->partialIndex);
+ ctx->partialIndex = ctx->blockSize;
+
+ /* XOR in K2. */
+ for (unsigned int index = 0; index < ctx->blockSize; index++) {
+ ctx->partialBlock[index] ^= ctx->k2[index];
+ }
+ }
+
+ /* Encrypt the block. */
+ if (cmac_UpdateState(ctx) != SECSuccess) {
+ return SECFailure;
+ }
+
+ /* Step 7 & 8: T = MSB_tlen(C_n); return T. */
+ PORT_Memcpy(result, ctx->lastBlock, max_result_len);
+ if (result_len != NULL) {
+ *result_len = max_result_len;
+ }
+ return SECSuccess;
+}
+
+void
+CMAC_Destroy(CMACContext *ctx, PRBool free_it)
+{
+ if (ctx == NULL) {
+ return;
+ }
+
+ if (ctx->cipherType == CMAC_AES) {
+ AES_DestroyContext(&ctx->cipher.aes, PR_FALSE);
+ }
+
+ /* Destroy everything in the context. This includes sensitive data in
+ * K1, K2, and lastBlock. */
+ PORT_Memset(ctx, 0, sizeof(*ctx));
+
+ if (free_it == PR_TRUE) {
+ PORT_Free(ctx);
+ }
+}
diff --git a/security/nss/lib/freebl/cmac.h b/security/nss/lib/freebl/cmac.h
new file mode 100644
index 000000000..6a6f42c79
--- /dev/null
+++ b/security/nss/lib/freebl/cmac.h
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _CMAC_H_
+#define _CMAC_H_
+
+typedef struct CMACContextStr CMACContext;
+
+SEC_BEGIN_PROTOS
+
+/* Enum for identifying the underlying block cipher we're using internally. */
+typedef enum {
+ CMAC_AES = 0
+} CMACCipher;
+
+/* Initialize an existing CMACContext struct. */
+SECStatus CMAC_Init(CMACContext *ctx, CMACCipher type,
+ const unsigned char *key, unsigned int key_len);
+
+/* Allocate and initialize a new CMAC context with the specified cipher and
+ * key. */
+CMACContext *CMAC_Create(CMACCipher type, const unsigned char *key,
+ unsigned int key_len);
+
+/* Called automatically by CMAC_*{Create,Init}(...). Only useful for restarting
+ * an already-started CMAC instance. */
+SECStatus CMAC_Begin(CMACContext *ctx);
+
+/* Add the specified bytes into the CMAC state. */
+SECStatus CMAC_Update(CMACContext *ctx, const unsigned char *data,
+ unsigned int data_len);
+
+/* Finalize the CMAC state and return the result. */
+SECStatus CMAC_Finish(CMACContext *ctx, unsigned char *result,
+ unsigned int *result_len,
+ unsigned int max_result_len);
+
+/* Note: CMAC_Clone isn't implemented here because AES doesn't expose a
+ * context-cloning operation. */
+
+/* Destroy a CMAC context, optionally freeing it. */
+void CMAC_Destroy(CMACContext *ctx, PRBool free_it);
+
+SEC_END_PROTOS
+
+#endif
diff --git a/security/nss/lib/freebl/config.mk b/security/nss/lib/freebl/config.mk
index 7ac50db65..918a66363 100644
--- a/security/nss/lib/freebl/config.mk
+++ b/security/nss/lib/freebl/config.mk
@@ -90,12 +90,7 @@ EXTRA_SHARED_LIBS += \
endif
endif
-ifeq (,$(filter-out DragonFly FreeBSD Linux NetBSD OpenBSD, $(OS_TARGET)))
-CFLAGS += -std=gnu99
-endif
-
ifeq ($(OS_ARCH), Darwin)
-CFLAGS += -std=gnu99
EXTRA_SHARED_LIBS += -dylib_file @executable_path/libplc4.dylib:$(DIST)/lib/libplc4.dylib -dylib_file @executable_path/libplds4.dylib:$(DIST)/lib/libplds4.dylib
endif
diff --git a/security/nss/lib/freebl/crypto_primitives.c b/security/nss/lib/freebl/crypto_primitives.c
index 49c8ca5ca..425f9fcc8 100644
--- a/security/nss/lib/freebl/crypto_primitives.c
+++ b/security/nss/lib/freebl/crypto_primitives.c
@@ -22,7 +22,7 @@ swap8b(PRUint64 value)
return (value);
}
-#elif !defined(_MSC_VER)
+#elif defined(IS_LITTLE_ENDIAN) && !defined(_MSC_VER) && !__has_builtin(__builtin_bswap64) && !((defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))))
PRUint64
swap8b(PRUint64 x)
diff --git a/security/nss/lib/freebl/crypto_primitives.h b/security/nss/lib/freebl/crypto_primitives.h
index f19601f4b..86a6927ad 100644
--- a/security/nss/lib/freebl/crypto_primitives.h
+++ b/security/nss/lib/freebl/crypto_primitives.h
@@ -11,6 +11,11 @@
#include <stdlib.h>
#include "prtypes.h"
+/* For non-clang platform */
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
/* Unfortunately this isn't always set when it should be. */
#if defined(HAVE_LONG_LONG)
@@ -29,11 +34,17 @@
/*
* FREEBL_HTONLL(x): swap bytes in a 64-bit integer.
*/
+#if defined(IS_LITTLE_ENDIAN)
#if defined(_MSC_VER)
#pragma intrinsic(_byteswap_uint64)
#define FREEBL_HTONLL(x) _byteswap_uint64(x)
+/* gcc doesn't have __has_builtin, but it does have __builtin_bswap64 */
+#elif __has_builtin(__builtin_bswap64) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+
+#define FREEBL_HTONLL(x) __builtin_bswap64(x)
+
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__x86_64))
PRUint64 swap8b(PRUint64 value);
@@ -48,4 +59,8 @@ PRUint64 swap8b(PRUint64 x);
#endif /* _MSC_VER */
-#endif /* HAVE_LONG_LONG */ \ No newline at end of file
+#else /* IS_LITTLE_ENDIAN */
+#define FREEBL_HTONLL(x) (x)
+#endif
+
+#endif /* HAVE_LONG_LONG */
diff --git a/security/nss/lib/freebl/ctr.c b/security/nss/lib/freebl/ctr.c
index 4d26a5b06..67ee72c0c 100644
--- a/security/nss/lib/freebl/ctr.c
+++ b/security/nss/lib/freebl/ctr.c
@@ -17,6 +17,10 @@
#include "rijndael.h"
#endif
+#if defined(__ARM_NEON) || defined(__ARM_NEON__)
+#include <arm_neon.h>
+#endif
+
SECStatus
CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
const unsigned char *param)
@@ -114,6 +118,15 @@ ctr_xor(unsigned char *target, const unsigned char *x,
const unsigned char *y, unsigned int count)
{
unsigned int i;
+#if defined(__ARM_NEON) || defined(__ARM_NEON__)
+ while (count >= 16) {
+ vst1q_u8(target, veorq_u8(vld1q_u8(x), vld1q_u8(y)));
+ target += 16;
+ x += 16;
+ y += 16;
+ count -= 16;
+ }
+#endif
for (i = 0; i < count; i++) {
*target++ = *x++ ^ *y++;
}
diff --git a/security/nss/lib/freebl/drbg.c b/security/nss/lib/freebl/drbg.c
index 70ae2618e..85e9e61b6 100644
--- a/security/nss/lib/freebl/drbg.c
+++ b/security/nss/lib/freebl/drbg.c
@@ -30,6 +30,7 @@
#define PRNG_ADDITONAL_DATA_CACHE_SIZE (8 * 1024) /* must be less than \
* PRNG_MAX_ADDITIONAL_BYTES \
*/
+#define PRNG_ENTROPY_BLOCK_SIZE SHA256_LENGTH
/* RESEED_COUNT is how many calls to the prng before we need to reseed
* under normal NIST rules, you must return an error. In the NSS case, we
@@ -96,6 +97,8 @@ struct RNGContextStr {
PRUint32 additionalAvail;
PRBool isValid; /* false if RNG reaches an invalid state */
PRBool isKatTest; /* true if running NIST PRNG KAT tests */
+ /* for continuous entropy check */
+ PRUint8 previousEntropyHash[SHA256_LENGTH];
};
typedef struct RNGContextStr RNGContext;
@@ -169,6 +172,82 @@ prng_instantiate(RNGContext *rng, const PRUint8 *bytes, unsigned int len)
return SECSuccess;
}
+static PRCallOnceType coRNGInitEntropy;
+
+static PRStatus
+prng_initEntropy(void)
+{
+ size_t length;
+ PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
+ SHA256Context ctx;
+
+ /* For FIPS 140-2 4.9.2 continuous random number generator test,
+ * fetch the initial entropy from the system RNG and keep it for
+ * later comparison. */
+ length = RNG_SystemRNG(block, sizeof(block));
+ if (length == 0) {
+ return PR_FAILURE; /* error is already set */
+ }
+ PORT_Assert(length == sizeof(block));
+
+ /* Store the hash of the entropy block rather than the block
+ * itself for backward secrecy. */
+ SHA256_Begin(&ctx);
+ SHA256_Update(&ctx, block, sizeof(block));
+ SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
+ sizeof(globalrng->previousEntropyHash));
+ PORT_Memset(block, 0, sizeof(block));
+ return PR_SUCCESS;
+}
+
+static SECStatus
+prng_getEntropy(PRUint8 *buffer, size_t requestLength)
+{
+ size_t total = 0;
+ PRUint8 block[PRNG_ENTROPY_BLOCK_SIZE];
+ PRUint8 hash[SHA256_LENGTH];
+ SHA256Context ctx;
+ SECStatus rv = SECSuccess;
+
+ if (PR_CallOnce(&coRNGInitEntropy, prng_initEntropy) != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+
+ /* For FIPS 140-2 4.9.2 continuous random generator test,
+ * iteratively fetch fixed sized blocks from the system and
+ * compare consecutive blocks. */
+ while (total < requestLength) {
+ size_t length = RNG_SystemRNG(block, sizeof(block));
+ if (length == 0) {
+ rv = SECFailure; /* error is already set */
+ goto out;
+ }
+ PORT_Assert(length == sizeof(block));
+
+ /* Store the hash of the entropy block rather than the block
+ * itself for backward secrecy. */
+ SHA256_Begin(&ctx);
+ SHA256_Update(&ctx, block, sizeof(block));
+ SHA256_End(&ctx, hash, NULL, sizeof(hash));
+
+ if (PORT_Memcmp(globalrng->previousEntropyHash, hash, sizeof(hash)) == 0) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ rv = SECFailure;
+ goto out;
+ }
+ PORT_Memcpy(globalrng->previousEntropyHash, hash, sizeof(hash));
+ length = PR_MIN(requestLength - total, sizeof(block));
+ PORT_Memcpy(buffer, block, length);
+ total += length;
+ buffer += length;
+ }
+
+out:
+ PORT_Memset(block, 0, sizeof block);
+ return rv;
+}
+
/*
* Update the global random number generator with more seeding
* material. Use the Hash_DRBG reseed algorithm from NIST SP-800-90
@@ -182,11 +261,15 @@ prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
{
PRUint8 noiseData[(sizeof rng->V_Data) + PRNG_SEEDLEN];
PRUint8 *noise = &noiseData[0];
+ SECStatus rv;
/* if entropy wasn't supplied, fetch it. (normal operation case) */
if (entropy == NULL) {
- entropy_len = (unsigned int)RNG_SystemRNG(
- &noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
+ entropy_len = PRNG_SEEDLEN;
+ rv = prng_getEntropy(&noiseData[sizeof rng->V_Data], entropy_len);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error is already set */
+ }
} else {
/* NOTE: this code is only available for testing, not to applications */
/* if entropy was too big for the stack variable, get it from malloc */
@@ -384,7 +467,6 @@ static PRStatus
rng_init(void)
{
PRUint8 bytes[PRNG_SEEDLEN * 2]; /* entropy + nonce */
- unsigned int numBytes;
SECStatus rv = SECSuccess;
if (globalrng == NULL) {
@@ -403,18 +485,17 @@ rng_init(void)
}
/* Try to get some seed data for the RNG */
- numBytes = (unsigned int)RNG_SystemRNG(bytes, sizeof bytes);
- PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
- if (numBytes != 0) {
+ rv = prng_getEntropy(bytes, sizeof bytes);
+ if (rv == SECSuccess) {
/* if this is our first call, instantiate, otherwise reseed
* prng_instantiate gets a new clean state, we want to mix
* any previous entropy we may have collected */
if (V(globalrng)[0] == 0) {
- rv = prng_instantiate(globalrng, bytes, numBytes);
+ rv = prng_instantiate(globalrng, bytes, sizeof bytes);
} else {
- rv = prng_reseed_test(globalrng, bytes, numBytes, NULL, 0);
+ rv = prng_reseed_test(globalrng, bytes, sizeof bytes, NULL, 0);
}
- memset(bytes, 0, numBytes);
+ memset(bytes, 0, sizeof bytes);
} else {
PZ_DestroyLock(globalrng->lock);
globalrng->lock = NULL;
diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c
index ddbcc2340..12330193a 100644
--- a/security/nss/lib/freebl/ec.c
+++ b/security/nss/lib/freebl/ec.c
@@ -24,7 +24,7 @@ static const ECMethod kMethods[] = {
static const ECMethod *
ec_get_method_from_name(ECCurveName name)
{
- int i;
+ unsigned long i;
for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) {
if (kMethods[i].name == name) {
return &kMethods[i];
diff --git a/security/nss/lib/freebl/ecl/curve25519_32.c b/security/nss/lib/freebl/ecl/curve25519_32.c
index 0122961e6..c28245680 100644
--- a/security/nss/lib/freebl/ecl/curve25519_32.c
+++ b/security/nss/lib/freebl/ecl/curve25519_32.c
@@ -1,390 +1,1213 @@
-/* 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/. */
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
/*
- * Derived from public domain code by Matthew Dempsky and D. J. Bernstein.
+ * Derived from machine-generated code via Fiat-Crypto:
+ * https://github.com/mit-plv/fiat-crypto and https://github.com/briansmith/ring
+ *
+ * The below captures notable changes:
+ *
+ * 1. Convert custom integer types to stdint.h types
*/
+#ifdef FREEBL_NO_DEPEND
+#include "../stubs.h"
+#endif
+
#include "ecl-priv.h"
-#include "mpi.h"
-#include <stdint.h>
-#include <stdio.h>
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9].
+ * fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc.
+ * Multiplication and carrying produce fe from fe_loose.
+ */
+typedef struct fe {
+ uint32_t v[10];
+} fe;
+
+/* fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc
+ * Addition and subtraction produce fe_loose from (fe, fe).
+ */
+typedef struct fe_loose {
+ uint32_t v[10];
+} fe_loose;
+
+#define assert_fe(f) \
+ do { \
+ for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \
+ PORT_Assert(f[_assert_fe_i] <= \
+ ((_assert_fe_i & 1) ? 0x2333333u : 0x4666666u)); \
+ } \
+ } while (0)
-typedef uint32_t elem[32];
+#define assert_fe_loose(f) \
+ do { \
+ for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \
+ PORT_Assert(f[_assert_fe_i] <= \
+ ((_assert_fe_i & 1) ? 0x6999999u : 0xd333332u)); \
+ } \
+ } while (0)
/*
- * Add two field elements.
- * out = a + b
+ * The function fiat_25519_subborrowx_u26 is a subtraction with borrow.
+ * Postconditions:
+ * out1 = (-arg1 + arg2 + -arg3) mod 2^26
+ * out2 = -⌊(-arg1 + arg2 + -arg3) / 2^26⌋
+ *
+ * Input Bounds:
+ * arg1: [0x0 ~> 0x1]
+ * arg2: [0x0 ~> 0x3ffffff]
+ * arg3: [0x0 ~> 0x3ffffff]
+ * Output Bounds:
+ * out1: [0x0 ~> 0x3ffffff]
+ * out2: [0x0 ~> 0x1]
*/
static void
-add(elem out, const elem a, const elem b)
-{
- uint32_t j;
- uint32_t u = 0;
- for (j = 0; j < 31; ++j) {
- u += a[j] + b[j];
- out[j] = u & 0xFF;
- u >>= 8;
- }
- u += a[31] + b[31];
- out[31] = u;
+fiat_25519_subborrowx_u26(uint32_t *out1, uint8_t *out2, uint8_t arg1, uint32_t arg2, uint32_t arg3)
+{
+ int32_t x1 = ((int32_t)(arg2 - arg1) - (int32_t)arg3);
+ int8_t x2 = (int8_t)(x1 >> 26);
+ uint32_t x3 = (x1 & UINT32_C(0x3ffffff));
+ *out1 = x3;
+ *out2 = (uint8_t)(0x0 - x2);
}
/*
- * Subtract two field elements.
- * out = a - b
+ * The function fiat_25519_subborrowx_u25 is a subtraction with borrow.
+ * Postconditions:
+ * out1 = (-arg1 + arg2 + -arg3) mod 2^25
+ * out2 = -⌊(-arg1 + arg2 + -arg3) / 2^25⌋
+ *
+ * Input Bounds:
+ * arg1: [0x0 ~> 0x1]
+ * arg2: [0x0 ~> 0x1ffffff]
+ * arg3: [0x0 ~> 0x1ffffff]
+ * Output Bounds:
+ * out1: [0x0 ~> 0x1ffffff]
+ * out2: [0x0 ~> 0x1]
*/
static void
-sub(elem out, const elem a, const elem b)
-{
- uint32_t j;
- uint32_t u;
- u = 218;
- for (j = 0; j < 31; ++j) {
- u += a[j] + 0xFF00 - b[j];
- out[j] = u & 0xFF;
- u >>= 8;
- }
- u += a[31] - b[31];
- out[31] = u;
+fiat_25519_subborrowx_u25(uint32_t *out1, uint8_t *out2, uint8_t arg1, uint32_t arg2, uint32_t arg3)
+{
+ int32_t x1 = ((int32_t)(arg2 - arg1) - (int32_t)arg3);
+ int8_t x2 = (int8_t)(x1 >> 25);
+ uint32_t x3 = (x1 & UINT32_C(0x1ffffff));
+ *out1 = x3;
+ *out2 = (uint8_t)(0x0 - x2);
}
/*
- * "Squeeze" an element after multiplication (and square).
+ * The function fiat_25519_addcarryx_u26 is an addition with carry.
+ * Postconditions:
+ * out1 = (arg1 + arg2 + arg3) mod 2^26
+ * out2 = ⌊(arg1 + arg2 + arg3) / 2^26⌋
+ *
+ * Input Bounds:
+ * arg1: [0x0 ~> 0x1]
+ * arg2: [0x0 ~> 0x3ffffff]
+ * arg3: [0x0 ~> 0x3ffffff]
+ * Output Bounds:
+ * out1: [0x0 ~> 0x3ffffff]
+ * out2: [0x0 ~> 0x1]
*/
static void
-squeeze(elem a)
-{
- uint32_t j;
- uint32_t u;
- u = 0;
- for (j = 0; j < 31; ++j) {
- u += a[j];
- a[j] = u & 0xFF;
- u >>= 8;
- }
- u += a[31];
- a[31] = u & 0x7F;
- u = 19 * (u >> 7);
- for (j = 0; j < 31; ++j) {
- u += a[j];
- a[j] = u & 0xFF;
- u >>= 8;
- }
- a[31] += u;
+fiat_25519_addcarryx_u26(uint32_t *out1, uint8_t *out2, uint8_t arg1, uint32_t arg2, uint32_t arg3)
+{
+ uint32_t x1 = ((arg1 + arg2) + arg3);
+ uint32_t x2 = (x1 & UINT32_C(0x3ffffff));
+ uint8_t x3 = (uint8_t)(x1 >> 26);
+ *out1 = x2;
+ *out2 = x3;
}
-static const elem minusp = { 19, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 128 };
-
/*
- * Reduce point a by 2^255-19
+ * The function fiat_25519_addcarryx_u25 is an addition with carry.
+ * Postconditions:
+ * out1 = (arg1 + arg2 + arg3) mod 2^25
+ * out2 = ⌊(arg1 + arg2 + arg3) / 2^25⌋
+ *
+ * Input Bounds:
+ * arg1: [0x0 ~> 0x1]
+ * arg2: [0x0 ~> 0x1ffffff]
+ * arg3: [0x0 ~> 0x1ffffff]
+ * Output Bounds:
+ * out1: [0x0 ~> 0x1ffffff]
+ * out2: [0x0 ~> 0x1]
*/
static void
-reduce(elem a)
+fiat_25519_addcarryx_u25(uint32_t *out1, uint8_t *out2, uint8_t arg1, uint32_t arg2, uint32_t arg3)
{
- elem aorig;
- uint32_t j;
- uint32_t negative;
+ uint32_t x1 = ((arg1 + arg2) + arg3);
+ uint32_t x2 = (x1 & UINT32_C(0x1ffffff));
+ uint8_t x3 = (uint8_t)(x1 >> 25);
+ *out1 = x2;
+ *out2 = x3;
+}
- for (j = 0; j < 32; ++j) {
- aorig[j] = a[j];
- }
- add(a, a, minusp);
- negative = 1 + ~((a[31] >> 7) & 1);
- for (j = 0; j < 32; ++j) {
- a[j] ^= negative & (aorig[j] ^ a[j]);
- }
+/*
+ * The function fiat_25519_cmovznz_u32 is a single-word conditional move.
+ * Postconditions:
+ * out1 = (if arg1 = 0 then arg2 else arg3)
+ *
+ * Input Bounds:
+ * arg1: [0x0 ~> 0x1]
+ * arg2: [0x0 ~> 0xffffffff]
+ * arg3: [0x0 ~> 0xffffffff]
+ * Output Bounds:
+ * out1: [0x0 ~> 0xffffffff]
+ */
+static void
+fiat_25519_cmovznz_u32(uint32_t *out1, uint8_t arg1, uint32_t arg2, uint32_t arg3)
+{
+ uint8_t x1 = (!(!arg1));
+ uint32_t x2 = ((int8_t)(0x0 - x1) & UINT32_C(0xffffffff));
+ uint32_t x3 = ((x2 & arg3) | ((~x2) & arg2));
+ *out1 = x3;
}
/*
- * Multiplication and squeeze
- * out = a * b
+ * The function fiat_25519_from_bytes deserializes a field element from bytes in little-endian order.
+ * Postconditions:
+ * eval out1 mod m = bytes_eval arg1 mod m
+ *
+ * Input Bounds:
+ * arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]]
+ * Output Bounds:
+ * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
*/
static void
-mult(elem out, const elem a, const elem b)
-{
- uint32_t i;
- uint32_t j;
- uint32_t u;
-
- for (i = 0; i < 32; ++i) {
- u = 0;
- for (j = 0; j <= i; ++j) {
- u += a[j] * b[i - j];
- }
- for (j = i + 1; j < 32; ++j) {
- u += 38 * a[j] * b[i + 32 - j];
- }
- out[i] = u;
- }
- squeeze(out);
+fiat_25519_from_bytes(uint32_t out1[10], const uint8_t arg1[32])
+{
+ uint32_t x1 = ((uint32_t)(arg1[31]) << 18);
+ uint32_t x2 = ((uint32_t)(arg1[30]) << 10);
+ uint32_t x3 = ((uint32_t)(arg1[29]) << 2);
+ uint32_t x4 = ((uint32_t)(arg1[28]) << 20);
+ uint32_t x5 = ((uint32_t)(arg1[27]) << 12);
+ uint32_t x6 = ((uint32_t)(arg1[26]) << 4);
+ uint32_t x7 = ((uint32_t)(arg1[25]) << 21);
+ uint32_t x8 = ((uint32_t)(arg1[24]) << 13);
+ uint32_t x9 = ((uint32_t)(arg1[23]) << 5);
+ uint32_t x10 = ((uint32_t)(arg1[22]) << 23);
+ uint32_t x11 = ((uint32_t)(arg1[21]) << 15);
+ uint32_t x12 = ((uint32_t)(arg1[20]) << 7);
+ uint32_t x13 = ((uint32_t)(arg1[19]) << 24);
+ uint32_t x14 = ((uint32_t)(arg1[18]) << 16);
+ uint32_t x15 = ((uint32_t)(arg1[17]) << 8);
+ uint8_t x16 = (arg1[16]);
+ uint32_t x17 = ((uint32_t)(arg1[15]) << 18);
+ uint32_t x18 = ((uint32_t)(arg1[14]) << 10);
+ uint32_t x19 = ((uint32_t)(arg1[13]) << 2);
+ uint32_t x20 = ((uint32_t)(arg1[12]) << 19);
+ uint32_t x21 = ((uint32_t)(arg1[11]) << 11);
+ uint32_t x22 = ((uint32_t)(arg1[10]) << 3);
+ uint32_t x23 = ((uint32_t)(arg1[9]) << 21);
+ uint32_t x24 = ((uint32_t)(arg1[8]) << 13);
+ uint32_t x25 = ((uint32_t)(arg1[7]) << 5);
+ uint32_t x26 = ((uint32_t)(arg1[6]) << 22);
+ uint32_t x27 = ((uint32_t)(arg1[5]) << 14);
+ uint32_t x28 = ((uint32_t)(arg1[4]) << 6);
+ uint32_t x29 = ((uint32_t)(arg1[3]) << 24);
+ uint32_t x30 = ((uint32_t)(arg1[2]) << 16);
+ uint32_t x31 = ((uint32_t)(arg1[1]) << 8);
+ uint8_t x32 = (arg1[0]);
+ uint32_t x33 = (x32 + (x31 + (x30 + x29)));
+ uint8_t x34 = (uint8_t)(x33 >> 26);
+ uint32_t x35 = (x33 & UINT32_C(0x3ffffff));
+ uint32_t x36 = (x3 + (x2 + x1));
+ uint32_t x37 = (x6 + (x5 + x4));
+ uint32_t x38 = (x9 + (x8 + x7));
+ uint32_t x39 = (x12 + (x11 + x10));
+ uint32_t x40 = (x16 + (x15 + (x14 + x13)));
+ uint32_t x41 = (x19 + (x18 + x17));
+ uint32_t x42 = (x22 + (x21 + x20));
+ uint32_t x43 = (x25 + (x24 + x23));
+ uint32_t x44 = (x28 + (x27 + x26));
+ uint32_t x45 = (x34 + x44);
+ uint8_t x46 = (uint8_t)(x45 >> 25);
+ uint32_t x47 = (x45 & UINT32_C(0x1ffffff));
+ uint32_t x48 = (x46 + x43);
+ uint8_t x49 = (uint8_t)(x48 >> 26);
+ uint32_t x50 = (x48 & UINT32_C(0x3ffffff));
+ uint32_t x51 = (x49 + x42);
+ uint8_t x52 = (uint8_t)(x51 >> 25);
+ uint32_t x53 = (x51 & UINT32_C(0x1ffffff));
+ uint32_t x54 = (x52 + x41);
+ uint32_t x55 = (x54 & UINT32_C(0x3ffffff));
+ uint8_t x56 = (uint8_t)(x40 >> 25);
+ uint32_t x57 = (x40 & UINT32_C(0x1ffffff));
+ uint32_t x58 = (x56 + x39);
+ uint8_t x59 = (uint8_t)(x58 >> 26);
+ uint32_t x60 = (x58 & UINT32_C(0x3ffffff));
+ uint32_t x61 = (x59 + x38);
+ uint8_t x62 = (uint8_t)(x61 >> 25);
+ uint32_t x63 = (x61 & UINT32_C(0x1ffffff));
+ uint32_t x64 = (x62 + x37);
+ uint8_t x65 = (uint8_t)(x64 >> 26);
+ uint32_t x66 = (x64 & UINT32_C(0x3ffffff));
+ uint32_t x67 = (x65 + x36);
+ out1[0] = x35;
+ out1[1] = x47;
+ out1[2] = x50;
+ out1[3] = x53;
+ out1[4] = x55;
+ out1[5] = x57;
+ out1[6] = x60;
+ out1[7] = x63;
+ out1[8] = x66;
+ out1[9] = x67;
+}
+
+static void
+fe_frombytes_strict(fe *h, const uint8_t s[32])
+{
+ // |fiat_25519_from_bytes| requires the top-most bit be clear.
+ PORT_Assert((s[31] & 0x80) == 0);
+ fiat_25519_from_bytes(h->v, s);
+ assert_fe(h->v);
+}
+
+static inline void
+fe_frombytes(fe *h, const uint8_t *s)
+{
+ uint8_t s_copy[32];
+ memcpy(s_copy, s, 32);
+ s_copy[31] &= 0x7f;
+ fe_frombytes_strict(h, s_copy);
}
/*
- * Multiplication
- * out = 121665 * a
+ * The function fiat_25519_to_bytes serializes a field element to bytes in little-endian order.
+ * Postconditions:
+ * out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
+ *
+ * Input Bounds:
+ * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
+ * Output Bounds:
+ * out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]]
*/
static void
-mult121665(elem out, const elem a)
+fiat_25519_to_bytes(uint8_t out1[32], const uint32_t arg1[10])
{
- uint32_t j;
- uint32_t u;
+ uint32_t x1;
+ uint8_t x2;
+ fiat_25519_subborrowx_u26(&x1, &x2, 0x0, (arg1[0]), UINT32_C(0x3ffffed));
+ uint32_t x3;
+ uint8_t x4;
+ fiat_25519_subborrowx_u25(&x3, &x4, x2, (arg1[1]), UINT32_C(0x1ffffff));
+ uint32_t x5;
+ uint8_t x6;
+ fiat_25519_subborrowx_u26(&x5, &x6, x4, (arg1[2]), UINT32_C(0x3ffffff));
+ uint32_t x7;
+ uint8_t x8;
+ fiat_25519_subborrowx_u25(&x7, &x8, x6, (arg1[3]), UINT32_C(0x1ffffff));
+ uint32_t x9;
+ uint8_t x10;
+ fiat_25519_subborrowx_u26(&x9, &x10, x8, (arg1[4]), UINT32_C(0x3ffffff));
+ uint32_t x11;
+ uint8_t x12;
+ fiat_25519_subborrowx_u25(&x11, &x12, x10, (arg1[5]), UINT32_C(0x1ffffff));
+ uint32_t x13;
+ uint8_t x14;
+ fiat_25519_subborrowx_u26(&x13, &x14, x12, (arg1[6]), UINT32_C(0x3ffffff));
+ uint32_t x15;
+ uint8_t x16;
+ fiat_25519_subborrowx_u25(&x15, &x16, x14, (arg1[7]), UINT32_C(0x1ffffff));
+ uint32_t x17;
+ uint8_t x18;
+ fiat_25519_subborrowx_u26(&x17, &x18, x16, (arg1[8]), UINT32_C(0x3ffffff));
+ uint32_t x19;
+ uint8_t x20;
+ fiat_25519_subborrowx_u25(&x19, &x20, x18, (arg1[9]), UINT32_C(0x1ffffff));
+ uint32_t x21;
+ fiat_25519_cmovznz_u32(&x21, x20, 0x0, UINT32_C(0xffffffff));
+ uint32_t x22;
+ uint8_t x23;
+ fiat_25519_addcarryx_u26(&x22, &x23, 0x0, x1, (x21 & UINT32_C(0x3ffffed)));
+ uint32_t x24;
+ uint8_t x25;
+ fiat_25519_addcarryx_u25(&x24, &x25, x23, x3, (x21 & UINT32_C(0x1ffffff)));
+ uint32_t x26;
+ uint8_t x27;
+ fiat_25519_addcarryx_u26(&x26, &x27, x25, x5, (x21 & UINT32_C(0x3ffffff)));
+ uint32_t x28;
+ uint8_t x29;
+ fiat_25519_addcarryx_u25(&x28, &x29, x27, x7, (x21 & UINT32_C(0x1ffffff)));
+ uint32_t x30;
+ uint8_t x31;
+ fiat_25519_addcarryx_u26(&x30, &x31, x29, x9, (x21 & UINT32_C(0x3ffffff)));
+ uint32_t x32;
+ uint8_t x33;
+ fiat_25519_addcarryx_u25(&x32, &x33, x31, x11, (x21 & UINT32_C(0x1ffffff)));
+ uint32_t x34;
+ uint8_t x35;
+ fiat_25519_addcarryx_u26(&x34, &x35, x33, x13, (x21 & UINT32_C(0x3ffffff)));
+ uint32_t x36;
+ uint8_t x37;
+ fiat_25519_addcarryx_u25(&x36, &x37, x35, x15, (x21 & UINT32_C(0x1ffffff)));
+ uint32_t x38;
+ uint8_t x39;
+ fiat_25519_addcarryx_u26(&x38, &x39, x37, x17, (x21 & UINT32_C(0x3ffffff)));
+ uint32_t x40;
+ uint8_t x41;
+ fiat_25519_addcarryx_u25(&x40, &x41, x39, x19, (x21 & UINT32_C(0x1ffffff)));
+ uint32_t x42 = (x40 << 6);
+ uint32_t x43 = (x38 << 4);
+ uint32_t x44 = (x36 << 3);
+ uint32_t x45 = (x34 * (uint32_t)0x2);
+ uint32_t x46 = (x30 << 6);
+ uint32_t x47 = (x28 << 5);
+ uint32_t x48 = (x26 << 3);
+ uint32_t x49 = (x24 << 2);
+ uint32_t x50 = (x22 >> 8);
+ uint8_t x51 = (uint8_t)(x22 & UINT8_C(0xff));
+ uint32_t x52 = (x50 >> 8);
+ uint8_t x53 = (uint8_t)(x50 & UINT8_C(0xff));
+ uint8_t x54 = (uint8_t)(x52 >> 8);
+ uint8_t x55 = (uint8_t)(x52 & UINT8_C(0xff));
+ uint32_t x56 = (x54 + x49);
+ uint32_t x57 = (x56 >> 8);
+ uint8_t x58 = (uint8_t)(x56 & UINT8_C(0xff));
+ uint32_t x59 = (x57 >> 8);
+ uint8_t x60 = (uint8_t)(x57 & UINT8_C(0xff));
+ uint8_t x61 = (uint8_t)(x59 >> 8);
+ uint8_t x62 = (uint8_t)(x59 & UINT8_C(0xff));
+ uint32_t x63 = (x61 + x48);
+ uint32_t x64 = (x63 >> 8);
+ uint8_t x65 = (uint8_t)(x63 & UINT8_C(0xff));
+ uint32_t x66 = (x64 >> 8);
+ uint8_t x67 = (uint8_t)(x64 & UINT8_C(0xff));
+ uint8_t x68 = (uint8_t)(x66 >> 8);
+ uint8_t x69 = (uint8_t)(x66 & UINT8_C(0xff));
+ uint32_t x70 = (x68 + x47);
+ uint32_t x71 = (x70 >> 8);
+ uint8_t x72 = (uint8_t)(x70 & UINT8_C(0xff));
+ uint32_t x73 = (x71 >> 8);
+ uint8_t x74 = (uint8_t)(x71 & UINT8_C(0xff));
+ uint8_t x75 = (uint8_t)(x73 >> 8);
+ uint8_t x76 = (uint8_t)(x73 & UINT8_C(0xff));
+ uint32_t x77 = (x75 + x46);
+ uint32_t x78 = (x77 >> 8);
+ uint8_t x79 = (uint8_t)(x77 & UINT8_C(0xff));
+ uint32_t x80 = (x78 >> 8);
+ uint8_t x81 = (uint8_t)(x78 & UINT8_C(0xff));
+ uint8_t x82 = (uint8_t)(x80 >> 8);
+ uint8_t x83 = (uint8_t)(x80 & UINT8_C(0xff));
+ uint8_t x84 = (uint8_t)(x82 & UINT8_C(0xff));
+ uint32_t x85 = (x32 >> 8);
+ uint8_t x86 = (uint8_t)(x32 & UINT8_C(0xff));
+ uint32_t x87 = (x85 >> 8);
+ uint8_t x88 = (uint8_t)(x85 & UINT8_C(0xff));
+ uint8_t x89 = (uint8_t)(x87 >> 8);
+ uint8_t x90 = (uint8_t)(x87 & UINT8_C(0xff));
+ uint32_t x91 = (x89 + x45);
+ uint32_t x92 = (x91 >> 8);
+ uint8_t x93 = (uint8_t)(x91 & UINT8_C(0xff));
+ uint32_t x94 = (x92 >> 8);
+ uint8_t x95 = (uint8_t)(x92 & UINT8_C(0xff));
+ uint8_t x96 = (uint8_t)(x94 >> 8);
+ uint8_t x97 = (uint8_t)(x94 & UINT8_C(0xff));
+ uint32_t x98 = (x96 + x44);
+ uint32_t x99 = (x98 >> 8);
+ uint8_t x100 = (uint8_t)(x98 & UINT8_C(0xff));
+ uint32_t x101 = (x99 >> 8);
+ uint8_t x102 = (uint8_t)(x99 & UINT8_C(0xff));
+ uint8_t x103 = (uint8_t)(x101 >> 8);
+ uint8_t x104 = (uint8_t)(x101 & UINT8_C(0xff));
+ uint32_t x105 = (x103 + x43);
+ uint32_t x106 = (x105 >> 8);
+ uint8_t x107 = (uint8_t)(x105 & UINT8_C(0xff));
+ uint32_t x108 = (x106 >> 8);
+ uint8_t x109 = (uint8_t)(x106 & UINT8_C(0xff));
+ uint8_t x110 = (uint8_t)(x108 >> 8);
+ uint8_t x111 = (uint8_t)(x108 & UINT8_C(0xff));
+ uint32_t x112 = (x110 + x42);
+ uint32_t x113 = (x112 >> 8);
+ uint8_t x114 = (uint8_t)(x112 & UINT8_C(0xff));
+ uint32_t x115 = (x113 >> 8);
+ uint8_t x116 = (uint8_t)(x113 & UINT8_C(0xff));
+ uint8_t x117 = (uint8_t)(x115 >> 8);
+ uint8_t x118 = (uint8_t)(x115 & UINT8_C(0xff));
+ out1[0] = x51;
+ out1[1] = x53;
+ out1[2] = x55;
+ out1[3] = x58;
+ out1[4] = x60;
+ out1[5] = x62;
+ out1[6] = x65;
+ out1[7] = x67;
+ out1[8] = x69;
+ out1[9] = x72;
+ out1[10] = x74;
+ out1[11] = x76;
+ out1[12] = x79;
+ out1[13] = x81;
+ out1[14] = x83;
+ out1[15] = x84;
+ out1[16] = x86;
+ out1[17] = x88;
+ out1[18] = x90;
+ out1[19] = x93;
+ out1[20] = x95;
+ out1[21] = x97;
+ out1[22] = x100;
+ out1[23] = x102;
+ out1[24] = x104;
+ out1[25] = x107;
+ out1[26] = x109;
+ out1[27] = x111;
+ out1[28] = x114;
+ out1[29] = x116;
+ out1[30] = x118;
+ out1[31] = x117;
+}
- u = 0;
- for (j = 0; j < 31; ++j) {
- u += 121665 * a[j];
- out[j] = u & 0xFF;
- u >>= 8;
- }
- u += 121665 * a[31];
- out[31] = u & 0x7F;
- u = 19 * (u >> 7);
- for (j = 0; j < 31; ++j) {
- u += out[j];
- out[j] = u & 0xFF;
- u >>= 8;
- }
- u += out[j];
- out[j] = u;
+static inline void
+fe_tobytes(uint8_t s[32], const fe *f)
+{
+ assert_fe(f->v);
+ fiat_25519_to_bytes(s, f->v);
+}
+
+/* h = f */
+static inline void
+fe_copy(fe *h, const fe *f)
+{
+ memmove(h, f, sizeof(fe));
+}
+
+static inline void
+fe_copy_lt(fe_loose *h, const fe *f)
+{
+ PORT_Assert(sizeof(fe) == sizeof(fe_loose));
+ memmove(h, f, sizeof(fe));
+}
+
+/*
+ * h = 0
+ */
+static inline void
+fe_0(fe *h)
+{
+ memset(h, 0, sizeof(fe));
}
/*
- * Square a and squeeze the result.
- * out = a * a
+ * h = 1
+ */
+static inline void
+fe_1(fe *h)
+{
+ memset(h, 0, sizeof(fe));
+ h->v[0] = 1;
+}
+/*
+ * The function fiat_25519_add adds two field elements.
+ * Postconditions:
+ * eval out1 mod m = (eval arg1 + eval arg2) mod m
+ *
+ * Input Bounds:
+ * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
+ * arg2: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
+ * Output Bounds:
+ * out1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]]
*/
static void
-square(elem out, const elem a)
-{
- uint32_t i;
- uint32_t j;
- uint32_t u;
-
- for (i = 0; i < 32; ++i) {
- u = 0;
- for (j = 0; j < i - j; ++j) {
- u += a[j] * a[i - j];
- }
- for (j = i + 1; j < i + 32 - j; ++j) {
- u += 38 * a[j] * a[i + 32 - j];
- }
- u *= 2;
- if ((i & 1) == 0) {
- u += a[i / 2] * a[i / 2];
- u += 38 * a[i / 2 + 16] * a[i / 2 + 16];
- }
- out[i] = u;
- }
- squeeze(out);
+fiat_25519_add(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10])
+{
+ uint32_t x1 = ((arg1[0]) + (arg2[0]));
+ uint32_t x2 = ((arg1[1]) + (arg2[1]));
+ uint32_t x3 = ((arg1[2]) + (arg2[2]));
+ uint32_t x4 = ((arg1[3]) + (arg2[3]));
+ uint32_t x5 = ((arg1[4]) + (arg2[4]));
+ uint32_t x6 = ((arg1[5]) + (arg2[5]));
+ uint32_t x7 = ((arg1[6]) + (arg2[6]));
+ uint32_t x8 = ((arg1[7]) + (arg2[7]));
+ uint32_t x9 = ((arg1[8]) + (arg2[8]));
+ uint32_t x10 = ((arg1[9]) + (arg2[9]));
+ out1[0] = x1;
+ out1[1] = x2;
+ out1[2] = x3;
+ out1[3] = x4;
+ out1[4] = x5;
+ out1[5] = x6;
+ out1[6] = x7;
+ out1[7] = x8;
+ out1[8] = x9;
+ out1[9] = x10;
}
/*
- * Constant time swap between r and s depending on b
+ * Add two field elements.
+ * h = f + g
+ */
+static inline void
+fe_add(fe_loose *h, const fe *f, const fe *g)
+{
+ assert_fe(f->v);
+ assert_fe(g->v);
+ fiat_25519_add(h->v, f->v, g->v);
+ assert_fe_loose(h->v);
+}
+
+/*
+ * The function fiat_25519_sub subtracts two field elements.
+ * Postconditions:
+ * eval out1 mod m = (eval arg1 - eval arg2) mod m
+ *
+ * Input Bounds:
+ * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
+ * arg2: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
+ * Output Bounds:
+ * out1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]]
*/
static void
-cswap(uint32_t p[64], uint32_t q[64], uint32_t b)
+fiat_25519_sub(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10])
{
- uint32_t j;
- uint32_t swap = 1 + ~b;
+ uint32_t x1 = ((UINT32_C(0x7ffffda) + (arg1[0])) - (arg2[0]));
+ uint32_t x2 = ((UINT32_C(0x3fffffe) + (arg1[1])) - (arg2[1]));
+ uint32_t x3 = ((UINT32_C(0x7fffffe) + (arg1[2])) - (arg2[2]));
+ uint32_t x4 = ((UINT32_C(0x3fffffe) + (arg1[3])) - (arg2[3]));
+ uint32_t x5 = ((UINT32_C(0x7fffffe) + (arg1[4])) - (arg2[4]));
+ uint32_t x6 = ((UINT32_C(0x3fffffe) + (arg1[5])) - (arg2[5]));
+ uint32_t x7 = ((UINT32_C(0x7fffffe) + (arg1[6])) - (arg2[6]));
+ uint32_t x8 = ((UINT32_C(0x3fffffe) + (arg1[7])) - (arg2[7]));
+ uint32_t x9 = ((UINT32_C(0x7fffffe) + (arg1[8])) - (arg2[8]));
+ uint32_t x10 = ((UINT32_C(0x3fffffe) + (arg1[9])) - (arg2[9]));
+ out1[0] = x1;
+ out1[1] = x2;
+ out1[2] = x3;
+ out1[3] = x4;
+ out1[4] = x5;
+ out1[5] = x6;
+ out1[6] = x7;
+ out1[7] = x8;
+ out1[8] = x9;
+ out1[9] = x10;
+}
- for (j = 0; j < 64; ++j) {
- const uint32_t t = swap & (p[j] ^ q[j]);
- p[j] ^= t;
- q[j] ^= t;
- }
+/*
+ * Subtract two field elements.
+ * h = f - g
+ */
+static void
+fe_sub(fe_loose *h, const fe *f, const fe *g)
+{
+ assert_fe(f->v);
+ assert_fe(g->v);
+ fiat_25519_sub(h->v, f->v, g->v);
+ assert_fe_loose(h->v);
}
/*
- * Montgomery ladder
+ * The function fiat_25519_carry_mul multiplies two field elements and reduces the result.
+ * Postconditions:
+ * eval out1 mod m = (eval arg1 * eval arg2) mod m
+ *
+ * Input Bounds:
+ * arg1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]]
+ * arg2: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]]
+ * Output Bounds:
+ * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]]
*/
static void
-monty(elem x_2_out, elem z_2_out,
- const elem point, const elem scalar)
-{
- uint32_t x_3[64] = { 0 };
- uint32_t x_2[64] = { 0 };
- uint32_t a0[64];
- uint32_t a1[64];
- uint32_t b0[64];
- uint32_t b1[64];
- uint32_t c1[64];
- uint32_t r[32];
- uint32_t s[32];
- uint32_t t[32];
- uint32_t u[32];
- uint32_t swap = 0;
- uint32_t k_t = 0;
- int j;
-
- for (j = 0; j < 32; ++j) {
- x_3[j] = point[j];
- }
- x_3[32] = 1;
- x_2[0] = 1;
-
- for (j = 254; j >= 0; --j) {
- k_t = (scalar[j >> 3] >> (j & 7)) & 1;
- swap ^= k_t;
- cswap(x_2, x_3, swap);
- swap = k_t;
- add(a0, x_2, x_2 + 32);
- sub(a0 + 32, x_2, x_2 + 32);
- add(a1, x_3, x_3 + 32);
- sub(a1 + 32, x_3, x_3 + 32);
- square(b0, a0);
- square(b0 + 32, a0 + 32);
- mult(b1, a1, a0 + 32);
- mult(b1 + 32, a1 + 32, a0);
- add(c1, b1, b1 + 32);
- sub(c1 + 32, b1, b1 + 32);
- square(r, c1 + 32);
- sub(s, b0, b0 + 32);
- mult121665(t, s);
- add(u, t, b0);
- mult(x_2, b0, b0 + 32);
- mult(x_2 + 32, s, u);
- square(x_3, c1);
- mult(x_3 + 32, r, point);
- }
+fiat_25519_carry_mul(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10])
+{
+ uint64_t x1 = ((uint64_t)(arg1[9]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x2 = ((uint64_t)(arg1[9]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x3 = ((uint64_t)(arg1[9]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x4 = ((uint64_t)(arg1[9]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x5 = ((uint64_t)(arg1[9]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x6 = ((uint64_t)(arg1[9]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x7 = ((uint64_t)(arg1[9]) * ((arg2[3]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x8 = ((uint64_t)(arg1[9]) * ((arg2[2]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x9 = ((uint64_t)(arg1[9]) * ((arg2[1]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x10 = ((uint64_t)(arg1[8]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x11 = ((uint64_t)(arg1[8]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x12 = ((uint64_t)(arg1[8]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x13 = ((uint64_t)(arg1[8]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x14 = ((uint64_t)(arg1[8]) * ((arg2[5]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x15 = ((uint64_t)(arg1[8]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x16 = ((uint64_t)(arg1[8]) * ((arg2[3]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x17 = ((uint64_t)(arg1[8]) * ((arg2[2]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x18 = ((uint64_t)(arg1[7]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x19 = ((uint64_t)(arg1[7]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x20 = ((uint64_t)(arg1[7]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x21 = ((uint64_t)(arg1[7]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x22 = ((uint64_t)(arg1[7]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x23 = ((uint64_t)(arg1[7]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x24 = ((uint64_t)(arg1[7]) * ((arg2[3]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x25 = ((uint64_t)(arg1[6]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x26 = ((uint64_t)(arg1[6]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x27 = ((uint64_t)(arg1[6]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x28 = ((uint64_t)(arg1[6]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x29 = ((uint64_t)(arg1[6]) * ((arg2[5]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x30 = ((uint64_t)(arg1[6]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x31 = ((uint64_t)(arg1[5]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x32 = ((uint64_t)(arg1[5]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x33 = ((uint64_t)(arg1[5]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x34 = ((uint64_t)(arg1[5]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x35 = ((uint64_t)(arg1[5]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x36 = ((uint64_t)(arg1[4]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x37 = ((uint64_t)(arg1[4]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x38 = ((uint64_t)(arg1[4]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x39 = ((uint64_t)(arg1[4]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x40 = ((uint64_t)(arg1[3]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x41 = ((uint64_t)(arg1[3]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x42 = ((uint64_t)(arg1[3]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x43 = ((uint64_t)(arg1[2]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x44 = ((uint64_t)(arg1[2]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13)));
+ uint64_t x45 = ((uint64_t)(arg1[1]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13))));
+ uint64_t x46 = ((uint64_t)(arg1[9]) * (arg2[0]));
+ uint64_t x47 = ((uint64_t)(arg1[8]) * (arg2[1]));
+ uint64_t x48 = ((uint64_t)(arg1[8]) * (arg2[0]));
+ uint64_t x49 = ((uint64_t)(arg1[7]) * (arg2[2]));
+ uint64_t x50 = ((uint64_t)(arg1[7]) * ((arg2[1]) * (uint32_t)0x2));
+ uint64_t x51 = ((uint64_t)(arg1[7]) * (arg2[0]));
+ uint64_t x52 = ((uint64_t)(arg1[6]) * (arg2[3]));
+ uint64_t x53 = ((uint64_t)(arg1[6]) * (arg2[2]));
+ uint64_t x54 = ((uint64_t)(arg1[6]) * (arg2[1]));
+ uint64_t x55 = ((uint64_t)(arg1[6]) * (arg2[0]));
+ uint64_t x56 = ((uint64_t)(arg1[5]) * (arg2[4]));
+ uint64_t x57 = ((uint64_t)(arg1[5]) * ((arg2[3]) * (uint32_t)0x2));
+ uint64_t x58 = ((uint64_t)(arg1[5]) * (arg2[2]));
+ uint64_t x59 = ((uint64_t)(arg1[5]) * ((arg2[1]) * (uint32_t)0x2));
+ uint64_t x60 = ((uint64_t)(arg1[5]) * (arg2[0]));
+ uint64_t x61 = ((uint64_t)(arg1[4]) * (arg2[5]));
+ uint64_t x62 = ((uint64_t)(arg1[4]) * (arg2[4]));
+ uint64_t x63 = ((uint64_t)(arg1[4]) * (arg2[3]));
+ uint64_t x64 = ((uint64_t)(arg1[4]) * (arg2[2]));
+ uint64_t x65 = ((uint64_t)(arg1[4]) * (arg2[1]));
+ uint64_t x66 = ((uint64_t)(arg1[4]) * (arg2[0]));
+ uint64_t x67 = ((uint64_t)(arg1[3]) * (arg2[6]));
+ uint64_t x68 = ((uint64_t)(arg1[3]) * ((arg2[5]) * (uint32_t)0x2));
+ uint64_t x69 = ((uint64_t)(arg1[3]) * (arg2[4]));
+ uint64_t x70 = ((uint64_t)(arg1[3]) * ((arg2[3]) * (uint32_t)0x2));
+ uint64_t x71 = ((uint64_t)(arg1[3]) * (arg2[2]));
+ uint64_t x72 = ((uint64_t)(arg1[3]) * ((arg2[1]) * (uint32_t)0x2));
+ uint64_t x73 = ((uint64_t)(arg1[3]) * (arg2[0]));
+ uint64_t x74 = ((uint64_t)(arg1[2]) * (arg2[7]));
+ uint64_t x75 = ((uint64_t)(arg1[2]) * (arg2[6]));
+ uint64_t x76 = ((uint64_t)(arg1[2]) * (arg2[5]));
+ uint64_t x77 = ((uint64_t)(arg1[2]) * (arg2[4]));
+ uint64_t x78 = ((uint64_t)(arg1[2]) * (arg2[3]));
+ uint64_t x79 = ((uint64_t)(arg1[2]) * (arg2[2]));
+ uint64_t x80 = ((uint64_t)(arg1[2]) * (arg2[1]));
+ uint64_t x81 = ((uint64_t)(arg1[2]) * (arg2[0]));
+ uint64_t x82 = ((uint64_t)(arg1[1]) * (arg2[8]));
+ uint64_t x83 = ((uint64_t)(arg1[1]) * ((arg2[7]) * (uint32_t)0x2));
+ uint64_t x84 = ((uint64_t)(arg1[1]) * (arg2[6]));
+ uint64_t x85 = ((uint64_t)(arg1[1]) * ((arg2[5]) * (uint32_t)0x2));
+ uint64_t x86 = ((uint64_t)(arg1[1]) * (arg2[4]));
+ uint64_t x87 = ((uint64_t)(arg1[1]) * ((arg2[3]) * (uint32_t)0x2));
+ uint64_t x88 = ((uint64_t)(arg1[1]) * (arg2[2]));
+ uint64_t x89 = ((uint64_t)(arg1[1]) * ((arg2[1]) * (uint32_t)0x2));
+ uint64_t x90 = ((uint64_t)(arg1[1]) * (arg2[0]));
+ uint64_t x91 = ((uint64_t)(arg1[0]) * (arg2[9]));
+ uint64_t x92 = ((uint64_t)(arg1[0]) * (arg2[8]));
+ uint64_t x93 = ((uint64_t)(arg1[0]) * (arg2[7]));
+ uint64_t x94 = ((uint64_t)(arg1[0]) * (arg2[6]));
+ uint64_t x95 = ((uint64_t)(arg1[0]) * (arg2[5]));
+ uint64_t x96 = ((uint64_t)(arg1[0]) * (arg2[4]));
+ uint64_t x97 = ((uint64_t)(arg1[0]) * (arg2[3]));
+ uint64_t x98 = ((uint64_t)(arg1[0]) * (arg2[2]));
+ uint64_t x99 = ((uint64_t)(arg1[0]) * (arg2[1]));
+ uint64_t x100 = ((uint64_t)(arg1[0]) * (arg2[0]));
+ uint64_t x101 = (x100 + (x45 + (x44 + (x42 + (x39 + (x35 + (x30 + (x24 + (x17 + x9)))))))));
+ uint64_t x102 = (x101 >> 26);
+ uint32_t x103 = (uint32_t)(x101 & UINT32_C(0x3ffffff));
+ uint64_t x104 = (x91 + (x82 + (x74 + (x67 + (x61 + (x56 + (x52 + (x49 + (x47 + x46)))))))));
+ uint64_t x105 = (x92 + (x83 + (x75 + (x68 + (x62 + (x57 + (x53 + (x50 + (x48 + x1)))))))));
+ uint64_t x106 = (x93 + (x84 + (x76 + (x69 + (x63 + (x58 + (x54 + (x51 + (x10 + x2)))))))));
+ uint64_t x107 = (x94 + (x85 + (x77 + (x70 + (x64 + (x59 + (x55 + (x18 + (x11 + x3)))))))));
+ uint64_t x108 = (x95 + (x86 + (x78 + (x71 + (x65 + (x60 + (x25 + (x19 + (x12 + x4)))))))));
+ uint64_t x109 = (x96 + (x87 + (x79 + (x72 + (x66 + (x31 + (x26 + (x20 + (x13 + x5)))))))));
+ uint64_t x110 = (x97 + (x88 + (x80 + (x73 + (x36 + (x32 + (x27 + (x21 + (x14 + x6)))))))));
+ uint64_t x111 = (x98 + (x89 + (x81 + (x40 + (x37 + (x33 + (x28 + (x22 + (x15 + x7)))))))));
+ uint64_t x112 = (x99 + (x90 + (x43 + (x41 + (x38 + (x34 + (x29 + (x23 + (x16 + x8)))))))));
+ uint64_t x113 = (x102 + x112);
+ uint64_t x114 = (x113 >> 25);
+ uint32_t x115 = (uint32_t)(x113 & UINT32_C(0x1ffffff));
+ uint64_t x116 = (x114 + x111);
+ uint64_t x117 = (x116 >> 26);
+ uint32_t x118 = (uint32_t)(x116 & UINT32_C(0x3ffffff));
+ uint64_t x119 = (x117 + x110);
+ uint64_t x120 = (x119 >> 25);
+ uint32_t x121 = (uint32_t)(x119 & UINT32_C(0x1ffffff));
+ uint64_t x122 = (x120 + x109);
+ uint64_t x123 = (x122 >> 26);
+ uint32_t x124 = (uint32_t)(x122 & UINT32_C(0x3ffffff));
+ uint64_t x125 = (x123 + x108);
+ uint64_t x126 = (x125 >> 25);
+ uint32_t x127 = (uint32_t)(x125 & UINT32_C(0x1ffffff));
+ uint64_t x128 = (x126 + x107);
+ uint64_t x129 = (x128 >> 26);
+ uint32_t x130 = (uint32_t)(x128 & UINT32_C(0x3ffffff));
+ uint64_t x131 = (x129 + x106);
+ uint64_t x132 = (x131 >> 25);
+ uint32_t x133 = (uint32_t)(x131 & UINT32_C(0x1ffffff));
+ uint64_t x134 = (x132 + x105);
+ uint64_t x135 = (x134 >> 26);
+ uint32_t x136 = (uint32_t)(x134 & UINT32_C(0x3ffffff));
+ uint64_t x137 = (x135 + x104);
+ uint64_t x138 = (x137 >> 25);
+ uint32_t x139 = (uint32_t)(x137 & UINT32_C(0x1ffffff));
+ uint64_t x140 = (x138 * (uint64_t)UINT8_C(0x13));
+ uint64_t x141 = (x103 + x140);
+ uint32_t x142 = (uint32_t)(x141 >> 26);
+ uint32_t x143 = (uint32_t)(x141 & UINT32_C(0x3ffffff));
+ uint32_t x144 = (x142 + x115);
+ uint32_t x145 = (x144 >> 25);
+ uint32_t x146 = (x144 & UINT32_C(0x1ffffff));
+ uint32_t x147 = (x145 + x118);
+ out1[0] = x143;
+ out1[1] = x146;
+ out1[2] = x147;
+ out1[3] = x121;
+ out1[4] = x124;
+ out1[5] = x127;
+ out1[6] = x130;
+ out1[7] = x133;
+ out1[8] = x136;
+ out1[9] = x139;
+}
- cswap(x_2, x_3, swap);
- for (j = 0; j < 32; ++j) {
- x_2_out[j] = x_2[j];
- }
- for (j = 0; j < 32; ++j) {
- z_2_out[j] = x_2[j + 32];
- }
+static void
+fe_mul(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10])
+{
+ assert_fe_loose(arg1);
+ assert_fe_loose(arg2);
+ fiat_25519_carry_mul(out1, arg1, arg2);
+ assert_fe(out1);
+}
+
+static void
+fe_mul_ttt(fe *h, const fe *f, const fe *g)
+{
+ fe_mul(h->v, f->v, g->v);
}
static void
-recip(elem out, const elem z)
-{
- elem z2;
- elem z9;
- elem z11;
- elem z2_5_0;
- elem z2_10_0;
- elem z2_20_0;
- elem z2_50_0;
- elem z2_100_0;
- elem t0;
- elem t1;
+fe_mul_tlt(fe *h, const fe_loose *f, const fe *g)
+{
+ fe_mul(h->v, f->v, g->v);
+}
+
+static void
+fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g)
+{
+ fe_mul(h->v, f->v, g->v);
+}
+
+static void
+fe_sq(uint32_t out[10], const uint32_t in1[10])
+{
+ const uint32_t x17 = in1[9];
+ const uint32_t x18 = in1[8];
+ const uint32_t x16 = in1[7];
+ const uint32_t x14 = in1[6];
+ const uint32_t x12 = in1[5];
+ const uint32_t x10 = in1[4];
+ const uint32_t x8 = in1[3];
+ const uint32_t x6 = in1[2];
+ const uint32_t x4 = in1[1];
+ const uint32_t x2 = in1[0];
+ uint64_t x19 = ((uint64_t)x2 * x2);
+ uint64_t x20 = ((uint64_t)(0x2 * x2) * x4);
+ uint64_t x21 = (0x2 * (((uint64_t)x4 * x4) + ((uint64_t)x2 * x6)));
+ uint64_t x22 = (0x2 * (((uint64_t)x4 * x6) + ((uint64_t)x2 * x8)));
+ uint64_t x23 = ((((uint64_t)x6 * x6) + ((uint64_t)(0x4 * x4) * x8)) + ((uint64_t)(0x2 * x2) * x10));
+ uint64_t x24 = (0x2 * ((((uint64_t)x6 * x8) + ((uint64_t)x4 * x10)) + ((uint64_t)x2 * x12)));
+ uint64_t x25 = (0x2 * (((((uint64_t)x8 * x8) + ((uint64_t)x6 * x10)) + ((uint64_t)x2 * x14)) + ((uint64_t)(0x2 * x4) * x12)));
+ uint64_t x26 = (0x2 * (((((uint64_t)x8 * x10) + ((uint64_t)x6 * x12)) + ((uint64_t)x4 * x14)) + ((uint64_t)x2 * x16)));
+ uint64_t x27 = (((uint64_t)x10 * x10) + (0x2 * ((((uint64_t)x6 * x14) + ((uint64_t)x2 * x18)) + (0x2 * (((uint64_t)x4 * x16) + ((uint64_t)x8 * x12))))));
+ uint64_t x28 = (0x2 * ((((((uint64_t)x10 * x12) + ((uint64_t)x8 * x14)) + ((uint64_t)x6 * x16)) + ((uint64_t)x4 * x18)) + ((uint64_t)x2 * x17)));
+ uint64_t x29 = (0x2 * (((((uint64_t)x12 * x12) + ((uint64_t)x10 * x14)) + ((uint64_t)x6 * x18)) + (0x2 * (((uint64_t)x8 * x16) + ((uint64_t)x4 * x17)))));
+ uint64_t x30 = (0x2 * (((((uint64_t)x12 * x14) + ((uint64_t)x10 * x16)) + ((uint64_t)x8 * x18)) + ((uint64_t)x6 * x17)));
+ uint64_t x31 = (((uint64_t)x14 * x14) + (0x2 * (((uint64_t)x10 * x18) + (0x2 * (((uint64_t)x12 * x16) + ((uint64_t)x8 * x17))))));
+ uint64_t x32 = (0x2 * ((((uint64_t)x14 * x16) + ((uint64_t)x12 * x18)) + ((uint64_t)x10 * x17)));
+ uint64_t x33 = (0x2 * ((((uint64_t)x16 * x16) + ((uint64_t)x14 * x18)) + ((uint64_t)(0x2 * x12) * x17)));
+ uint64_t x34 = (0x2 * (((uint64_t)x16 * x18) + ((uint64_t)x14 * x17)));
+ uint64_t x35 = (((uint64_t)x18 * x18) + ((uint64_t)(0x4 * x16) * x17));
+ uint64_t x36 = ((uint64_t)(0x2 * x18) * x17);
+ uint64_t x37 = ((uint64_t)(0x2 * x17) * x17);
+ uint64_t x38 = (x27 + (x37 << 0x4));
+ uint64_t x39 = (x38 + (x37 << 0x1));
+ uint64_t x40 = (x39 + x37);
+ uint64_t x41 = (x26 + (x36 << 0x4));
+ uint64_t x42 = (x41 + (x36 << 0x1));
+ uint64_t x43 = (x42 + x36);
+ uint64_t x44 = (x25 + (x35 << 0x4));
+ uint64_t x45 = (x44 + (x35 << 0x1));
+ uint64_t x46 = (x45 + x35);
+ uint64_t x47 = (x24 + (x34 << 0x4));
+ uint64_t x48 = (x47 + (x34 << 0x1));
+ uint64_t x49 = (x48 + x34);
+ uint64_t x50 = (x23 + (x33 << 0x4));
+ uint64_t x51 = (x50 + (x33 << 0x1));
+ uint64_t x52 = (x51 + x33);
+ uint64_t x53 = (x22 + (x32 << 0x4));
+ uint64_t x54 = (x53 + (x32 << 0x1));
+ uint64_t x55 = (x54 + x32);
+ uint64_t x56 = (x21 + (x31 << 0x4));
+ uint64_t x57 = (x56 + (x31 << 0x1));
+ uint64_t x58 = (x57 + x31);
+ uint64_t x59 = (x20 + (x30 << 0x4));
+ uint64_t x60 = (x59 + (x30 << 0x1));
+ uint64_t x61 = (x60 + x30);
+ uint64_t x62 = (x19 + (x29 << 0x4));
+ uint64_t x63 = (x62 + (x29 << 0x1));
+ uint64_t x64 = (x63 + x29);
+ uint64_t x65 = (x64 >> 0x1a);
+ uint32_t x66 = ((uint32_t)x64 & 0x3ffffff);
+ uint64_t x67 = (x65 + x61);
+ uint64_t x68 = (x67 >> 0x19);
+ uint32_t x69 = ((uint32_t)x67 & 0x1ffffff);
+ uint64_t x70 = (x68 + x58);
+ uint64_t x71 = (x70 >> 0x1a);
+ uint32_t x72 = ((uint32_t)x70 & 0x3ffffff);
+ uint64_t x73 = (x71 + x55);
+ uint64_t x74 = (x73 >> 0x19);
+ uint32_t x75 = ((uint32_t)x73 & 0x1ffffff);
+ uint64_t x76 = (x74 + x52);
+ uint64_t x77 = (x76 >> 0x1a);
+ uint32_t x78 = ((uint32_t)x76 & 0x3ffffff);
+ uint64_t x79 = (x77 + x49);
+ uint64_t x80 = (x79 >> 0x19);
+ uint32_t x81 = ((uint32_t)x79 & 0x1ffffff);
+ uint64_t x82 = (x80 + x46);
+ uint64_t x83 = (x82 >> 0x1a);
+ uint32_t x84 = ((uint32_t)x82 & 0x3ffffff);
+ uint64_t x85 = (x83 + x43);
+ uint64_t x86 = (x85 >> 0x19);
+ uint32_t x87 = ((uint32_t)x85 & 0x1ffffff);
+ uint64_t x88 = (x86 + x40);
+ uint64_t x89 = (x88 >> 0x1a);
+ uint32_t x90 = ((uint32_t)x88 & 0x3ffffff);
+ uint64_t x91 = (x89 + x28);
+ uint64_t x92 = (x91 >> 0x19);
+ uint32_t x93 = ((uint32_t)x91 & 0x1ffffff);
+ uint64_t x94 = (x66 + (0x13 * x92));
+ uint32_t x95 = (uint32_t)(x94 >> 0x1a);
+ uint32_t x96 = ((uint32_t)x94 & 0x3ffffff);
+ uint32_t x97 = (x95 + x69);
+ uint32_t x98 = (x97 >> 0x19);
+ uint32_t x99 = (x97 & 0x1ffffff);
+ out[0] = x96;
+ out[1] = x99;
+ out[2] = (x98 + x72);
+ out[3] = x75;
+ out[4] = x78;
+ out[5] = x81;
+ out[6] = x84;
+ out[7] = x87;
+ out[8] = x90;
+ out[9] = x93;
+}
+
+static void
+fe_sq_tl(fe *h, const fe_loose *f)
+{
+ fe_sq(h->v, f->v);
+}
+
+static void
+fe_sq_tt(fe *h, const fe *f)
+{
+ fe_sq(h->v, f->v);
+}
+
+static inline void
+fe_loose_invert(fe *out, const fe_loose *z)
+{
+ fe t0, t1, t2, t3;
int i;
- /* 2 */ square(z2, z);
- /* 4 */ square(t1, z2);
- /* 8 */ square(t0, t1);
- /* 9 */ mult(z9, t0, z);
- /* 11 */ mult(z11, z9, z2);
- /* 22 */ square(t0, z11);
- /* 2^5 - 2^0 = 31 */ mult(z2_5_0, t0, z9);
-
- /* 2^6 - 2^1 */ square(t0, z2_5_0);
- /* 2^7 - 2^2 */ square(t1, t0);
- /* 2^8 - 2^3 */ square(t0, t1);
- /* 2^9 - 2^4 */ square(t1, t0);
- /* 2^10 - 2^5 */ square(t0, t1);
- /* 2^10 - 2^0 */ mult(z2_10_0, t0, z2_5_0);
-
- /* 2^11 - 2^1 */ square(t0, z2_10_0);
- /* 2^12 - 2^2 */ square(t1, t0);
- /* 2^20 - 2^10 */
- for (i = 2; i < 10; i += 2) {
- square(t0, t1);
- square(t1, t0);
+ fe_sq_tl(&t0, z);
+ fe_sq_tt(&t1, &t0);
+ for (i = 1; i < 2; ++i) {
+ fe_sq_tt(&t1, &t1);
+ }
+ fe_mul_tlt(&t1, z, &t1);
+ fe_mul_ttt(&t0, &t0, &t1);
+ fe_sq_tt(&t2, &t0);
+ fe_mul_ttt(&t1, &t1, &t2);
+ fe_sq_tt(&t2, &t1);
+ for (i = 1; i < 5; ++i) {
+ fe_sq_tt(&t2, &t2);
+ }
+ fe_mul_ttt(&t1, &t2, &t1);
+ fe_sq_tt(&t2, &t1);
+ for (i = 1; i < 10; ++i) {
+ fe_sq_tt(&t2, &t2);
+ }
+ fe_mul_ttt(&t2, &t2, &t1);
+ fe_sq_tt(&t3, &t2);
+ for (i = 1; i < 20; ++i) {
+ fe_sq_tt(&t3, &t3);
}
- /* 2^20 - 2^0 */ mult(z2_20_0, t1, z2_10_0);
-
- /* 2^21 - 2^1 */ square(t0, z2_20_0);
- /* 2^22 - 2^2 */ square(t1, t0);
- /* 2^40 - 2^20 */
- for (i = 2; i < 20; i += 2) {
- square(t0, t1);
- square(t1, t0);
+ fe_mul_ttt(&t2, &t3, &t2);
+ fe_sq_tt(&t2, &t2);
+ for (i = 1; i < 10; ++i) {
+ fe_sq_tt(&t2, &t2);
}
- /* 2^40 - 2^0 */ mult(t0, t1, z2_20_0);
-
- /* 2^41 - 2^1 */ square(t1, t0);
- /* 2^42 - 2^2 */ square(t0, t1);
- /* 2^50 - 2^10 */
- for (i = 2; i < 10; i += 2) {
- square(t1, t0);
- square(t0, t1);
+ fe_mul_ttt(&t1, &t2, &t1);
+ fe_sq_tt(&t2, &t1);
+ for (i = 1; i < 50; ++i) {
+ fe_sq_tt(&t2, &t2);
}
- /* 2^50 - 2^0 */ mult(z2_50_0, t0, z2_10_0);
-
- /* 2^51 - 2^1 */ square(t0, z2_50_0);
- /* 2^52 - 2^2 */ square(t1, t0);
- /* 2^100 - 2^50 */
- for (i = 2; i < 50; i += 2) {
- square(t0, t1);
- square(t1, t0);
+ fe_mul_ttt(&t2, &t2, &t1);
+ fe_sq_tt(&t3, &t2);
+ for (i = 1; i < 100; ++i) {
+ fe_sq_tt(&t3, &t3);
}
- /* 2^100 - 2^0 */ mult(z2_100_0, t1, z2_50_0);
-
- /* 2^101 - 2^1 */ square(t1, z2_100_0);
- /* 2^102 - 2^2 */ square(t0, t1);
- /* 2^200 - 2^100 */
- for (i = 2; i < 100; i += 2) {
- square(t1, t0);
- square(t0, t1);
+ fe_mul_ttt(&t2, &t3, &t2);
+ fe_sq_tt(&t2, &t2);
+ for (i = 1; i < 50; ++i) {
+ fe_sq_tt(&t2, &t2);
}
- /* 2^200 - 2^0 */ mult(t1, t0, z2_100_0);
-
- /* 2^201 - 2^1 */ square(t0, t1);
- /* 2^202 - 2^2 */ square(t1, t0);
- /* 2^250 - 2^50 */
- for (i = 2; i < 50; i += 2) {
- square(t0, t1);
- square(t1, t0);
+ fe_mul_ttt(&t1, &t2, &t1);
+ fe_sq_tt(&t1, &t1);
+ for (i = 1; i < 5; ++i) {
+ fe_sq_tt(&t1, &t1);
}
- /* 2^250 - 2^0 */ mult(t0, t1, z2_50_0);
+ fe_mul_ttt(out, &t1, &t0);
+}
- /* 2^251 - 2^1 */ square(t1, t0);
- /* 2^252 - 2^2 */ square(t0, t1);
- /* 2^253 - 2^3 */ square(t1, t0);
- /* 2^254 - 2^4 */ square(t0, t1);
- /* 2^255 - 2^5 */ square(t1, t0);
- /* 2^255 - 21 */ mult(out, t1, z11);
+static inline void
+fe_invert(fe *out, const fe *z)
+{
+ fe_loose l;
+ fe_copy_lt(&l, z);
+ fe_loose_invert(out, &l);
}
-/*
- * Computes q = Curve25519(p, s)
+/* Replace (f,g) with (g,f) if b == 1;
+ * replace (f,g) with (f,g) if b == 0.
+ *
+ * Preconditions: b in {0,1}
*/
-SECStatus
-ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p)
-{
- elem point = { 0 };
- elem x_2 = { 0 };
- elem z_2 = { 0 };
- elem X = { 0 };
- elem scalar = { 0 };
- uint32_t i;
-
- /* read and mask scalar */
- for (i = 0; i < 32; ++i) {
- scalar[i] = s[i];
+static inline void
+fe_cswap(fe *f, fe *g, unsigned int b)
+{
+ PORT_Assert(b < 2);
+ unsigned int i;
+ b = 0 - b;
+ for (i = 0; i < 10; i++) {
+ uint32_t x = f->v[i] ^ g->v[i];
+ x &= b;
+ f->v[i] ^= x;
+ g->v[i] ^= x;
}
- scalar[0] &= 0xF8;
- scalar[31] &= 0x7F;
- scalar[31] |= 64;
+}
- /* read and mask point */
- for (i = 0; i < 32; ++i) {
- point[i] = p[i];
- }
- point[31] &= 0x7F;
-
- monty(x_2, z_2, point, scalar);
- recip(z_2, z_2);
- mult(X, x_2, z_2);
- reduce(X);
- for (i = 0; i < 32; ++i) {
- q[i] = X[i];
+/* NOTE: based on fiat-crypto fe_mul, edited for in2=121666, 0, 0.*/
+static inline void
+fe_mul_121666(uint32_t out[10], const uint32_t in1[10])
+{
+ const uint32_t x20 = in1[9];
+ const uint32_t x21 = in1[8];
+ const uint32_t x19 = in1[7];
+ const uint32_t x17 = in1[6];
+ const uint32_t x15 = in1[5];
+ const uint32_t x13 = in1[4];
+ const uint32_t x11 = in1[3];
+ const uint32_t x9 = in1[2];
+ const uint32_t x7 = in1[1];
+ const uint32_t x5 = in1[0];
+ const uint32_t x38 = 0;
+ const uint32_t x39 = 0;
+ const uint32_t x37 = 0;
+ const uint32_t x35 = 0;
+ const uint32_t x33 = 0;
+ const uint32_t x31 = 0;
+ const uint32_t x29 = 0;
+ const uint32_t x27 = 0;
+ const uint32_t x25 = 0;
+ const uint32_t x23 = 121666;
+ uint64_t x40 = ((uint64_t)x23 * x5);
+ uint64_t x41 = (((uint64_t)x23 * x7) + ((uint64_t)x25 * x5));
+ uint64_t x42 = ((((uint64_t)(0x2 * x25) * x7) + ((uint64_t)x23 * x9)) + ((uint64_t)x27 * x5));
+ uint64_t x43 = (((((uint64_t)x25 * x9) + ((uint64_t)x27 * x7)) + ((uint64_t)x23 * x11)) + ((uint64_t)x29 * x5));
+ uint64_t x44 = (((((uint64_t)x27 * x9) + (0x2 * (((uint64_t)x25 * x11) + ((uint64_t)x29 * x7)))) + ((uint64_t)x23 * x13)) + ((uint64_t)x31 * x5));
+ uint64_t x45 = (((((((uint64_t)x27 * x11) + ((uint64_t)x29 * x9)) + ((uint64_t)x25 * x13)) + ((uint64_t)x31 * x7)) + ((uint64_t)x23 * x15)) + ((uint64_t)x33 * x5));
+ uint64_t x46 = (((((0x2 * ((((uint64_t)x29 * x11) + ((uint64_t)x25 * x15)) + ((uint64_t)x33 * x7))) + ((uint64_t)x27 * x13)) + ((uint64_t)x31 * x9)) + ((uint64_t)x23 * x17)) + ((uint64_t)x35 * x5));
+ uint64_t x47 = (((((((((uint64_t)x29 * x13) + ((uint64_t)x31 * x11)) + ((uint64_t)x27 * x15)) + ((uint64_t)x33 * x9)) + ((uint64_t)x25 * x17)) + ((uint64_t)x35 * x7)) + ((uint64_t)x23 * x19)) + ((uint64_t)x37 * x5));
+ uint64_t x48 = (((((((uint64_t)x31 * x13) + (0x2 * (((((uint64_t)x29 * x15) + ((uint64_t)x33 * x11)) + ((uint64_t)x25 * x19)) + ((uint64_t)x37 * x7)))) + ((uint64_t)x27 * x17)) + ((uint64_t)x35 * x9)) + ((uint64_t)x23 * x21)) + ((uint64_t)x39 * x5));
+ uint64_t x49 = (((((((((((uint64_t)x31 * x15) + ((uint64_t)x33 * x13)) + ((uint64_t)x29 * x17)) + ((uint64_t)x35 * x11)) + ((uint64_t)x27 * x19)) + ((uint64_t)x37 * x9)) + ((uint64_t)x25 * x21)) + ((uint64_t)x39 * x7)) + ((uint64_t)x23 * x20)) + ((uint64_t)x38 * x5));
+ uint64_t x50 = (((((0x2 * ((((((uint64_t)x33 * x15) + ((uint64_t)x29 * x19)) + ((uint64_t)x37 * x11)) + ((uint64_t)x25 * x20)) + ((uint64_t)x38 * x7))) + ((uint64_t)x31 * x17)) + ((uint64_t)x35 * x13)) + ((uint64_t)x27 * x21)) + ((uint64_t)x39 * x9));
+ uint64_t x51 = (((((((((uint64_t)x33 * x17) + ((uint64_t)x35 * x15)) + ((uint64_t)x31 * x19)) + ((uint64_t)x37 * x13)) + ((uint64_t)x29 * x21)) + ((uint64_t)x39 * x11)) + ((uint64_t)x27 * x20)) + ((uint64_t)x38 * x9));
+ uint64_t x52 = (((((uint64_t)x35 * x17) + (0x2 * (((((uint64_t)x33 * x19) + ((uint64_t)x37 * x15)) + ((uint64_t)x29 * x20)) + ((uint64_t)x38 * x11)))) + ((uint64_t)x31 * x21)) + ((uint64_t)x39 * x13));
+ uint64_t x53 = (((((((uint64_t)x35 * x19) + ((uint64_t)x37 * x17)) + ((uint64_t)x33 * x21)) + ((uint64_t)x39 * x15)) + ((uint64_t)x31 * x20)) + ((uint64_t)x38 * x13));
+ uint64_t x54 = (((0x2 * ((((uint64_t)x37 * x19) + ((uint64_t)x33 * x20)) + ((uint64_t)x38 * x15))) + ((uint64_t)x35 * x21)) + ((uint64_t)x39 * x17));
+ uint64_t x55 = (((((uint64_t)x37 * x21) + ((uint64_t)x39 * x19)) + ((uint64_t)x35 * x20)) + ((uint64_t)x38 * x17));
+ uint64_t x56 = (((uint64_t)x39 * x21) + (0x2 * (((uint64_t)x37 * x20) + ((uint64_t)x38 * x19))));
+ uint64_t x57 = (((uint64_t)x39 * x20) + ((uint64_t)x38 * x21));
+ uint64_t x58 = ((uint64_t)(0x2 * x38) * x20);
+ uint64_t x59 = (x48 + (x58 << 0x4));
+ uint64_t x60 = (x59 + (x58 << 0x1));
+ uint64_t x61 = (x60 + x58);
+ uint64_t x62 = (x47 + (x57 << 0x4));
+ uint64_t x63 = (x62 + (x57 << 0x1));
+ uint64_t x64 = (x63 + x57);
+ uint64_t x65 = (x46 + (x56 << 0x4));
+ uint64_t x66 = (x65 + (x56 << 0x1));
+ uint64_t x67 = (x66 + x56);
+ uint64_t x68 = (x45 + (x55 << 0x4));
+ uint64_t x69 = (x68 + (x55 << 0x1));
+ uint64_t x70 = (x69 + x55);
+ uint64_t x71 = (x44 + (x54 << 0x4));
+ uint64_t x72 = (x71 + (x54 << 0x1));
+ uint64_t x73 = (x72 + x54);
+ uint64_t x74 = (x43 + (x53 << 0x4));
+ uint64_t x75 = (x74 + (x53 << 0x1));
+ uint64_t x76 = (x75 + x53);
+ uint64_t x77 = (x42 + (x52 << 0x4));
+ uint64_t x78 = (x77 + (x52 << 0x1));
+ uint64_t x79 = (x78 + x52);
+ uint64_t x80 = (x41 + (x51 << 0x4));
+ uint64_t x81 = (x80 + (x51 << 0x1));
+ uint64_t x82 = (x81 + x51);
+ uint64_t x83 = (x40 + (x50 << 0x4));
+ uint64_t x84 = (x83 + (x50 << 0x1));
+ uint64_t x85 = (x84 + x50);
+ uint64_t x86 = (x85 >> 0x1a);
+ uint32_t x87 = ((uint32_t)x85 & 0x3ffffff);
+ uint64_t x88 = (x86 + x82);
+ uint64_t x89 = (x88 >> 0x19);
+ uint32_t x90 = ((uint32_t)x88 & 0x1ffffff);
+ uint64_t x91 = (x89 + x79);
+ uint64_t x92 = (x91 >> 0x1a);
+ uint32_t x93 = ((uint32_t)x91 & 0x3ffffff);
+ uint64_t x94 = (x92 + x76);
+ uint64_t x95 = (x94 >> 0x19);
+ uint32_t x96 = ((uint32_t)x94 & 0x1ffffff);
+ uint64_t x97 = (x95 + x73);
+ uint64_t x98 = (x97 >> 0x1a);
+ uint32_t x99 = ((uint32_t)x97 & 0x3ffffff);
+ uint64_t x100 = (x98 + x70);
+ uint64_t x101 = (x100 >> 0x19);
+ uint32_t x102 = ((uint32_t)x100 & 0x1ffffff);
+ uint64_t x103 = (x101 + x67);
+ uint64_t x104 = (x103 >> 0x1a);
+ uint32_t x105 = ((uint32_t)x103 & 0x3ffffff);
+ uint64_t x106 = (x104 + x64);
+ uint64_t x107 = (x106 >> 0x19);
+ uint32_t x108 = ((uint32_t)x106 & 0x1ffffff);
+ uint64_t x109 = (x107 + x61);
+ uint64_t x110 = (x109 >> 0x1a);
+ uint32_t x111 = ((uint32_t)x109 & 0x3ffffff);
+ uint64_t x112 = (x110 + x49);
+ uint64_t x113 = (x112 >> 0x19);
+ uint32_t x114 = ((uint32_t)x112 & 0x1ffffff);
+ uint64_t x115 = (x87 + (0x13 * x113));
+ uint32_t x116 = (uint32_t)(x115 >> 0x1a);
+ uint32_t x117 = ((uint32_t)x115 & 0x3ffffff);
+ uint32_t x118 = (x116 + x90);
+ uint32_t x119 = (x118 >> 0x19);
+ uint32_t x120 = (x118 & 0x1ffffff);
+ out[0] = x117;
+ out[1] = x120;
+ out[2] = (x119 + x93);
+ out[3] = x96;
+ out[4] = x99;
+ out[5] = x102;
+ out[6] = x105;
+ out[7] = x108;
+ out[8] = x111;
+ out[9] = x114;
+}
+
+static void
+fe_mul_121666_tl(fe *h, const fe_loose *f)
+{
+ assert_fe_loose(f->v);
+ fe_mul_121666(h->v, f->v);
+ assert_fe(h->v);
+}
+
+SECStatus
+ec_Curve25519_mul(PRUint8 *out, const PRUint8 *scalar, const PRUint8 *point)
+{
+ fe x1, x2, z2, x3, z3, tmp0, tmp1;
+ fe_loose x2l, z2l, x3l, tmp0l, tmp1l;
+ unsigned int swap = 0;
+ unsigned int b;
+ int pos;
+ uint8_t e[32];
+
+ memcpy(e, scalar, 32);
+ e[0] &= 0xF8;
+ e[31] &= 0x7F;
+ e[31] |= 0x40;
+
+ fe_frombytes(&x1, point);
+ fe_1(&x2);
+ fe_0(&z2);
+ fe_copy(&x3, &x1);
+ fe_1(&z3);
+
+ for (pos = 254; pos >= 0; --pos) {
+ b = e[pos / 8] >> (pos & 7);
+ b &= 1;
+ swap ^= b;
+ fe_cswap(&x2, &x3, swap);
+ fe_cswap(&z2, &z3, swap);
+ swap = b;
+ fe_sub(&tmp0l, &x3, &z3);
+ fe_sub(&tmp1l, &x2, &z2);
+ fe_add(&x2l, &x2, &z2);
+ fe_add(&z2l, &x3, &z3);
+ fe_mul_tll(&z3, &tmp0l, &x2l);
+ fe_mul_tll(&z2, &z2l, &tmp1l);
+ fe_sq_tl(&tmp0, &tmp1l);
+ fe_sq_tl(&tmp1, &x2l);
+ fe_add(&x3l, &z3, &z2);
+ fe_sub(&z2l, &z3, &z2);
+ fe_mul_ttt(&x2, &tmp1, &tmp0);
+ fe_sub(&tmp1l, &tmp1, &tmp0);
+ fe_sq_tl(&z2, &z2l);
+ fe_mul_121666_tl(&z3, &tmp1l);
+ fe_sq_tl(&x3, &x3l);
+ fe_add(&tmp0l, &tmp0, &z3);
+ fe_mul_ttt(&z3, &x1, &z2);
+ fe_mul_tll(&z2, &tmp1l, &tmp0l);
}
+
+ fe_cswap(&x2, &x3, swap);
+ fe_cswap(&z2, &z3, swap);
+
+ fe_invert(&z2, &z2);
+ fe_mul_ttt(&x2, &x2, &z2);
+ fe_tobytes(out, &x2);
+
+ memset(x1.v, 0, sizeof(x1));
+ memset(x2.v, 0, sizeof(x2));
+ memset(z2.v, 0, sizeof(z2));
+ memset(x3.v, 0, sizeof(x3));
+ memset(z3.v, 0, sizeof(z3));
+ memset(x2l.v, 0, sizeof(x2l));
+ memset(z2l.v, 0, sizeof(z2l));
+ memset(x3l.v, 0, sizeof(x3l));
+ memset(e, 0, sizeof(e));
return 0;
}
diff --git a/security/nss/lib/freebl/exports.gyp b/security/nss/lib/freebl/exports.gyp
index ca0b6dafd..af5c782a5 100644
--- a/security/nss/lib/freebl/exports.gyp
+++ b/security/nss/lib/freebl/exports.gyp
@@ -27,6 +27,7 @@
},
{
'files': [
+ 'cmac.h',
'alghmac.h',
'blapi.h',
'blake2b.h',
diff --git a/security/nss/lib/freebl/fipsfreebl.c b/security/nss/lib/freebl/fipsfreebl.c
index 2328a677f..93a9a0de7 100644
--- a/security/nss/lib/freebl/fipsfreebl.c
+++ b/security/nss/lib/freebl/fipsfreebl.c
@@ -15,8 +15,10 @@
#include "seccomon.h" /* Required for RSA and DSA. */
#include "secerr.h"
#include "prtypes.h"
+#include "secitem.h"
+#include "pkcs11t.h"
-#include "ec.h" /* Required for ECDSA */
+#include "ec.h" /* Required for EC */
/*
* different platforms have different ways of calling and initial entry point
@@ -288,6 +290,8 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
/* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
+ static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
+
/* AES Known Ciphertext (128-bit key). */
static const PRUint8 aes_ecb128_known_ciphertext[] = {
0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
@@ -299,6 +303,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
};
+ static const PRUint8 aes_gcm128_known_ciphertext[] = {
+ 0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
+ 0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
+ 0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
+ 0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
+ };
+
/* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
@@ -310,6 +321,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
};
+ static const PRUint8 aes_gcm192_known_ciphertext[] = {
+ 0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
+ 0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
+ 0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
+ 0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
+ };
+
/* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
@@ -321,18 +339,29 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
};
+ static const PRUint8 aes_gcm256_known_ciphertext[] = {
+ 0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
+ 0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
+ 0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
+ 0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
+ };
+
const PRUint8 *aes_ecb_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
const PRUint8 *aes_cbc_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
+ const PRUint8 *aes_gcm_known_ciphertext =
+ (aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
+
/* AES variables. */
- PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
- PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
+ PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
+ PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context;
unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted;
+ CK_GCM_PARAMS gcmParams;
SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */
@@ -455,6 +484,69 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
return (SECFailure);
}
+ /******************************************************/
+ /* AES-GCM Single-Round Known Answer Encryption Test. */
+ /******************************************************/
+
+ gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
+ gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
+ gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
+ gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
+ gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
+ aes_context = AES_CreateContext(aes_known_key,
+ (PRUint8 *)&gcmParams,
+ NSS_AES_GCM, PR_TRUE, aes_key_size,
+ FIPS_AES_BLOCK_SIZE);
+
+ if (aes_context == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return (SECFailure);
+ }
+
+ aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
+ &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
+ aes_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH);
+
+ AES_DestroyContext(aes_context, PR_TRUE);
+
+ if ((aes_status != SECSuccess) ||
+ (aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
+ (PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
+ FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+
+ /******************************************************/
+ /* AES-GCM Single-Round Known Answer Decryption Test. */
+ /******************************************************/
+
+ aes_context = AES_CreateContext(aes_known_key,
+ (PRUint8 *)&gcmParams,
+ NSS_AES_GCM, PR_FALSE, aes_key_size,
+ FIPS_AES_BLOCK_SIZE);
+
+ if (aes_context == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return (SECFailure);
+ }
+
+ aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
+ &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
+ aes_gcm_known_ciphertext,
+ FIPS_AES_ENCRYPT_LENGTH * 2);
+
+ AES_DestroyContext(aes_context, PR_TRUE);
+
+ if ((aes_status != SECSuccess) ||
+ (aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
+ (PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
+ FIPS_AES_DECRYPT_LENGTH) != 0)) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+
return (SECSuccess);
}
@@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
"Firefox and ThunderBird are awesome!"
};
- unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
+ unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
unsigned char sig[2 * MAX_ECKEY_LEN];
SECItem signature, digest;
ECPrivateKey *ecdsa_private_key = NULL;
@@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
/* ECDSA Single-Round Known Answer Signature Test. */
/***************************************************/
- ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
+ ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
digest.type = siBuffer;
- digest.data = sha1;
- digest.len = SHA1_LENGTH;
+ digest.data = sha256;
+ digest.len = SHA256_LENGTH;
memset(sig, 0, sizeof sig);
signature.type = siBuffer;
@@ -1181,10 +1273,83 @@ loser:
}
static SECStatus
-freebl_fips_ECDSA_PowerUpSelfTest()
+freebl_fips_ECDH_Test(ECParams *ecparams)
{
- /* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
+ /* ECDH Known result (reused old CAVS vector) */
+ static const PRUint8 ecdh_known_pub_key_1[] = {
+ EC_POINT_FORM_UNCOMPRESSED,
+ /* pubX */
+ 0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
+ 0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
+ 0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
+ 0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
+ /* pubY */
+ 0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
+ 0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
+ 0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
+ 0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
+ };
+ static const PRUint8 ecdh_known_priv_key_2[] = {
+ 0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
+ 0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
+ 0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
+ 0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
+ };
+ static const PRUint8 ecdh_known_hash_result[] = {
+ 0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
+ 0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
+ 0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
+ 0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
+ };
+
+ SECItem ecdh_priv_2, ecdh_pub_1;
+ SECItem ZZ = { 0, 0, 0 };
+ SECStatus ecdhStatus = SECSuccess;
+ PRUint8 computed_hash_result[HASH_LENGTH_MAX];
+
+ ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
+ ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
+ ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
+ ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
+
+ /* Generates a new EC key pair. The private key is a supplied
+ * random value (in seed) and the public key is the result of
+ * performing a scalar point multiplication of that value with
+ * the curve's base point.
+ */
+ ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
+ if (ecdhStatus != SECSuccess) {
+ goto loser;
+ }
+ ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
+ if (ecdhStatus != SECSuccess) {
+ goto loser;
+ }
+
+ if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
+ sizeof(ecdh_known_hash_result)) != 0) {
+ ecdhStatus = SECFailure;
+ goto loser;
+ }
+
+loser:
+ if (ZZ.data) {
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+ }
+
+ if (ecdhStatus != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+ return (SECSuccess);
+}
+
+static SECStatus
+freebl_fips_EC_PowerUpSelfTest()
+{
+
+ /* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
static const unsigned char p256_prime[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -1217,7 +1382,7 @@ freebl_fips_ECDSA_PowerUpSelfTest()
static const unsigned char p256_encoding[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
};
- static const ECParams ecdsa_known_P256_Params = {
+ static const ECParams ec_known_P256_Params = {
NULL, ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
@@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest()
0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
- 0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
- 0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
- 0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
- 0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
+ 0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
+ 0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
+ 0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
+ 0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
};
ECParams ecparams;
@@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest()
SECStatus rv;
/* ECDSA GF(p) prime field curve test */
- ecparams = ecdsa_known_P256_Params;
+ ecparams = ec_known_P256_Params;
rv = freebl_fips_ECDSA_Test(&ecparams,
ecdsa_known_P256_signature,
sizeof ecdsa_known_P256_signature);
if (rv != SECSuccess) {
return (SECFailure);
}
+ /* ECDH GF(p) prime field curve test */
+ rv = freebl_fips_ECDH_Test(&ecparams);
+ if (rv != SECSuccess) {
+ return (SECFailure);
+ }
return (SECSuccess);
}
@@ -1418,6 +1588,138 @@ freebl_fips_DSA_PowerUpSelfTest(void)
}
static SECStatus
+freebl_fips_DH_PowerUpSelfTest(void)
+{
+ /* DH Known P (2048-bits) */
+ static const PRUint8 dh_known_P[] = {
+ 0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
+ 0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
+ 0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
+ 0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
+ 0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
+ 0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
+ 0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
+ 0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
+ 0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
+ 0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
+ 0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
+ 0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
+ 0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
+ 0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
+ 0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
+ 0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
+ 0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
+ 0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
+ 0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
+ 0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
+ 0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
+ 0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
+ 0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
+ 0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
+ 0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
+ 0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
+ 0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
+ 0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
+ 0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
+ 0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
+ 0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
+ 0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
+ };
+
+ static const PRUint8 dh_known_Y_1[] = {
+ 0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
+ 0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
+ 0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
+ 0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
+ 0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
+ 0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
+ 0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
+ 0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
+ 0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
+ 0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
+ 0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
+ 0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
+ 0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
+ 0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
+ 0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
+ 0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
+ 0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
+ 0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
+ 0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
+ 0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
+ 0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
+ 0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
+ 0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
+ 0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
+ 0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
+ 0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
+ 0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
+ 0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
+ 0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
+ 0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
+ 0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
+ 0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
+ };
+
+ static const PRUint8 dh_known_x_2[] = {
+ 0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
+ 0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
+ 0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
+ 0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
+ };
+
+ static const PRUint8 dh_known_hash_result[] = {
+ 0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
+ 0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
+ 0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
+ 0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
+ };
+
+ /* DH variables. */
+ SECStatus dhStatus;
+ SECItem dh_prime;
+ SECItem dh_pub_key_1;
+ SECItem dh_priv_key_2;
+ SECItem ZZ = { 0, 0, 0 };
+ PRUint8 computed_hash_result[HASH_LENGTH_MAX];
+
+ dh_prime.data = (PRUint8 *)dh_known_P;
+ dh_prime.len = sizeof(dh_known_P);
+ dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
+ dh_pub_key_1.len = sizeof(dh_known_Y_1);
+ dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
+ dh_priv_key_2.len = sizeof(dh_known_x_2);
+
+ /* execute the derive */
+ dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
+ if (dhStatus != SECSuccess) {
+ goto loser;
+ }
+
+ dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
+ if (dhStatus != SECSuccess) {
+ goto loser;
+ }
+
+ if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
+ sizeof(dh_known_hash_result)) != 0) {
+ dhStatus = SECFailure;
+ goto loser;
+ }
+
+loser:
+ if (ZZ.data) {
+ SECITEM_FreeItem(&ZZ, PR_FALSE);
+ }
+
+ if (dhStatus != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return (SECFailure);
+ }
+ return (SECSuccess);
+}
+
+static SECStatus
freebl_fips_RNG_PowerUpSelfTest(void)
{
static const PRUint8 Q[] = {
@@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
return rv;
/* NOTE: RSA can only be tested in full freebl. It requires access to
- * the locking primitives */
+ * the locking primitives */
/* RSA Power-Up SelfTest(s). */
rv = freebl_fips_RSA_PowerUpSelfTest();
@@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess)
return rv;
- /* ECDSA Power-Up SelfTest(s). */
- rv = freebl_fips_ECDSA_PowerUpSelfTest();
+ /* DH Power-Up SelfTest(s). */
+ rv = freebl_fips_DH_PowerUpSelfTest();
+
+ if (rv != SECSuccess)
+ return rv;
+
+ /* EC Power-Up SelfTest(s). */
+ rv = freebl_fips_EC_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp
index 288ff07a3..7ea5c3750 100644
--- a/security/nss/lib/freebl/freebl.gyp
+++ b/security/nss/lib/freebl/freebl.gyp
@@ -76,11 +76,11 @@
'__SSSE3__',
],
}],
- [ 'OS=="android"', {
- # On Android we can't use any of the hardware acceleration :(
- 'defines!': [
- '__ARM_NEON__',
- '__ARM_NEON',
+ [ 'target_arch=="arm"', {
+ # Gecko doesn't support non-NEON platform on Android, but tier-3
+ # platform such as Linux/arm will need it
+ 'cflags_mozilla': [
+ '-mfpu=neon'
],
}],
],
@@ -107,7 +107,7 @@
],
}],
# macOS build doesn't use cflags.
- [ 'OS=="mac"', {
+ [ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mpclmul', '-maes'
@@ -117,6 +117,69 @@
]
},
{
+ 'target_name': 'gcm-aes-aarch64_c_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'gcm-aarch64.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ],
+ 'cflags': [
+ '-march=armv8-a+crypto'
+ ],
+ 'cflags_mozilla': [
+ '-march=armv8-a+crypto'
+ ]
+ },
+ {
+ 'target_name': 'gcm-aes-ppc_c_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'gcm-ppc.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ],
+ 'cflags': [
+ '-mcrypto',
+ '-maltivec'
+ ],
+ 'cflags_mozilla': [
+ '-mcrypto',
+ '-maltivec'
+ ]
+ },
+ {
+ 'target_name': 'armv8_c_lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'aes-armv8.c',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ],
+ 'conditions': [
+ [ 'target_arch=="arm"', {
+ 'cflags': [
+ '-march=armv8-a',
+ '-mfpu=crypto-neon-fp-armv8'
+ ],
+ 'cflags_mozilla': [
+ '-march=armv8-a',
+ '-mfpu=crypto-neon-fp-armv8'
+ ],
+ }, 'target_arch=="arm64" or target_arch=="aarch64"', {
+ 'cflags': [
+ '-march=armv8-a+crypto'
+ ],
+ 'cflags_mozilla': [
+ '-march=armv8-a+crypto'
+ ],
+ }]
+ ]
+ },
+ {
'target_name': 'freebl',
'type': 'static_library',
'sources': [
@@ -126,9 +189,9 @@
'<(DEPTH)/exports.gyp:nss_exports'
]
},
- # For test builds, build a static freebl library so we can statically
- # link it into the test build binary. This way we don't have to
- # dlopen() the shared lib but can directly call freebl functions.
+ # Build a static freebl library so we can statically link it into
+ # the binary. This way we don't have to dlopen() the shared lib
+ # but can directly call freebl functions.
{
'target_name': 'freebl_static',
'type': 'static_library',
@@ -144,6 +207,20 @@
'dependencies': [
'gcm-aes-x86_c_lib',
],
+ }, 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
+ 'dependencies': [
+ 'armv8_c_lib'
+ ],
+ }],
+ [ 'target_arch=="arm64" or target_arch=="aarch64"', {
+ 'dependencies': [
+ 'gcm-aes-aarch64_c_lib',
+ ],
+ }],
+ [ 'target_arch=="ppc64le"', {
+ 'dependencies': [
+ 'gcm-aes-ppc_c_lib',
+ ],
}],
[ 'OS=="linux"', {
'defines!': [
@@ -154,7 +231,7 @@
],
'conditions': [
[ 'target_arch=="x64"', {
- # The AES assembler code doesn't work in static test builds.
+ # The AES assembler code doesn't work in static builds.
# The linker complains about non-relocatable code, and I
# currently don't know how to fix this properly.
'sources!': [
@@ -181,8 +258,22 @@
'dependencies': [
'gcm-aes-x86_c_lib',
]
+ }, 'target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64"', {
+ 'dependencies': [
+ 'armv8_c_lib',
+ ],
+ }],
+ [ 'target_arch=="arm64" or target_arch=="aarch64"', {
+ 'dependencies': [
+ 'gcm-aes-aarch64_c_lib',
+ ],
+ }],
+ [ 'target_arch=="ppc64" or target_arch=="ppc64le"', {
+ 'dependencies': [
+ 'gcm-aes-ppc_c_lib',
+ ],
}],
- [ 'OS!="linux" and OS!="android"', {
+ [ 'OS!="linux"', {
'conditions': [
[ 'moz_fold_libs==0', {
'dependencies': [
@@ -194,7 +285,8 @@
],
}],
],
- }, 'target_arch=="x64"', {
+ }],
+ [ '(OS=="linux" or OS=="android") and target_arch=="x64"', {
'dependencies': [
'intel-gcm-wrap_c_lib',
],
@@ -221,6 +313,43 @@
]
},
},
+ {
+ 'target_name': 'freebl_64int_3',
+ 'includes': [
+ 'freebl_base.gypi',
+ ],
+ 'type': 'shared_library',
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ 'hw-acc-crypto',
+ ],
+ },
+ {
+ 'target_name': 'freebl_64fpu_3',
+ 'includes': [
+ 'freebl_base.gypi',
+ ],
+ 'type': 'shared_library',
+ 'sources': [
+ 'mpi/mpi_sparc.c',
+ 'mpi/mpv_sparcv9.s',
+ 'mpi/montmulfv9.s',
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports',
+ 'hw-acc-crypto',
+ ],
+ 'asflags_mozilla': [
+ '-mcpu=v9', '-Wa,-xarch=v9a'
+ ],
+ 'defines': [
+ 'MP_NO_MP_WORD',
+ 'MP_USE_UINT_DIGIT',
+ 'MP_ASSEMBLY_MULTIPLY',
+ 'MP_USING_MONT_MULF',
+ 'MP_MONT_USE_MP_MUL',
+ ],
+ },
],
'conditions': [
[ 'OS=="linux"', {
@@ -260,15 +389,6 @@
'MP_API_COMPATIBLE'
],
'conditions': [
- [ 'OS=="mac"', {
- 'xcode_settings': {
- # I'm not sure since when this is supported.
- # But I hope that doesn't matter. We also assume this is x86/x64.
- 'OTHER_CFLAGS': [
- '-std=gnu99',
- ],
- },
- }],
[ 'OS=="win" and target_arch=="ia32"', {
'msvs_settings': {
'VCCLCompilerTool': {
@@ -323,14 +443,6 @@
'FREEBL_LOWHASH',
'FREEBL_NO_DEPEND',
],
- 'cflags': [
- '-std=gnu99',
- ],
- }],
- [ 'OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
- 'cflags': [
- '-std=gnu99',
- ],
}],
[ 'OS=="linux" or OS=="android"', {
'conditions': [
@@ -367,6 +479,11 @@
'ARMHF',
],
}],
+ [ 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
+ 'defines': [
+ 'USE_HW_AES',
+ ],
+ }],
],
}],
],
diff --git a/security/nss/lib/freebl/freebl_base.gypi b/security/nss/lib/freebl/freebl_base.gypi
index 76df71497..f2d1304fd 100644
--- a/security/nss/lib/freebl/freebl_base.gypi
+++ b/security/nss/lib/freebl/freebl_base.gypi
@@ -5,6 +5,7 @@
'sources': [
'aeskeywrap.c',
'alg2268.c',
+ 'cmac.c',
'alghmac.c',
'arcfive.c',
'arcfour.c',
@@ -99,7 +100,7 @@
}],
[ 'OS=="win"', {
'libraries': [
- 'advapi32.lib',
+ '-ladvapi32',
],
'conditions': [
[ 'cc_use_gnu_ld!=1 and target_arch=="x64"', {
diff --git a/security/nss/lib/freebl/gcm-aarch64.c b/security/nss/lib/freebl/gcm-aarch64.c
new file mode 100644
index 000000000..3f3c046d7
--- /dev/null
+++ b/security/nss/lib/freebl/gcm-aarch64.c
@@ -0,0 +1,96 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+#include "gcm.h"
+#include "secerr.h"
+
+/* old gcc doesn't support some poly64x2_t intrinsic */
+#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
+ (defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
+
+#include <arm_neon.h>
+
+SECStatus
+gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
+{
+ uint8x16_t ci = vrbitq_u8(vreinterpretq_u8_u64(ghash->x));
+ vst1q_u8(outbuf, ci);
+ return SECSuccess;
+}
+
+SECStatus
+gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
+ unsigned int count)
+{
+ const poly64x2_t p = vdupq_n_p64(0x87);
+ const uint8x16_t zero = vdupq_n_u8(0);
+ const uint64x2_t h = ghash->h;
+ uint64x2_t ci = ghash->x;
+ unsigned int i;
+ uint8x16_t z_low, z_high;
+ uint8x16_t t_low, t_high;
+ poly64x2_t t1;
+ uint8x16_t t2;
+
+ for (i = 0; i < count; i++, buf += 16) {
+ ci = vreinterpretq_u64_u8(veorq_u8(vreinterpretq_u8_u64(ci),
+ vrbitq_u8(vld1q_u8(buf))));
+
+ /* Do binary mult ghash->X = Ci * ghash->H. */
+ z_low = vreinterpretq_u8_p128(
+ vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u64(ci)),
+ (poly64_t)vget_low_p64(vreinterpretq_p64_u64(h))));
+ z_high = vreinterpretq_u8_p128(
+ vmull_high_p64(vreinterpretq_p64_u64(ci), vreinterpretq_p64_u64(h)));
+ t1 = vreinterpretq_p64_u8(
+ vextq_u8(vreinterpretq_u8_u64(h), vreinterpretq_u8_u64(h), 8));
+ t_low = vreinterpretq_u8_p128(
+ vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u64(ci)),
+ (poly64_t)vget_low_p64(t1)));
+ t_high = vreinterpretq_u8_p128(vmull_high_p64(vreinterpretq_p64_u64(ci), t1));
+ t2 = veorq_u8(t_high, t_low);
+ z_low = veorq_u8(z_low, vextq_u8(zero, t2, 8));
+ z_high = veorq_u8(z_high, vextq_u8(t2, zero, 8));
+
+ /* polynomial reduction */
+ t2 = vreinterpretq_u8_p128(vmull_high_p64(vreinterpretq_p64_u8(z_high), p));
+ z_high = veorq_u8(z_high, vextq_u8(t2, zero, 8));
+ z_low = veorq_u8(z_low, vextq_u8(zero, t2, 8));
+ ci = veorq_u64(vreinterpretq_u64_u8(z_low),
+ vreinterpretq_u64_p128(
+ vmull_p64((poly64_t)vget_low_p64(vreinterpretq_p64_u8(z_high)),
+ (poly64_t)vget_low_p64(p))));
+ }
+
+ ghash->x = ci;
+ return SECSuccess;
+}
+
+SECStatus
+gcm_HashInit_hw(gcmHashContext *ghash)
+{
+ /* Workaround of "used uninitialized in this function" error */
+ uint64x2_t h = vdupq_n_u64(0);
+
+ ghash->ghash_mul = gcm_HashMult_hw;
+ ghash->x = vdupq_n_u64(0);
+ h = vsetq_lane_u64(__builtin_bswap64(ghash->h_low), h, 1);
+ h = vsetq_lane_u64(__builtin_bswap64(ghash->h_high), h, 0);
+ h = vreinterpretq_u64_u8(vrbitq_u8(vreinterpretq_u8_u64(h)));
+ ghash->h = h;
+ ghash->hw = PR_TRUE;
+ return SECSuccess;
+}
+
+SECStatus
+gcm_HashZeroX_hw(gcmHashContext *ghash)
+{
+ ghash->x = vdupq_n_u64(0);
+ return SECSuccess;
+}
+
+#endif /* defined(__clang__) || (defined(__GNUC__) && __GNUC__ > 6) */
diff --git a/security/nss/lib/freebl/gcm-ppc.c b/security/nss/lib/freebl/gcm-ppc.c
new file mode 100644
index 000000000..9bd4f2956
--- /dev/null
+++ b/security/nss/lib/freebl/gcm-ppc.c
@@ -0,0 +1,109 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef FREEBL_NO_DEPEND
+#include "stubs.h"
+#endif
+#include "gcm.h"
+#include "secerr.h"
+
+#if defined(USE_PPC_CRYPTO)
+
+SECStatus
+gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
+{
+ vec_xst_be((vec_u8)ghash->x, 0, outbuf);
+ return SECSuccess;
+}
+
+static vec_u64
+vpmsumd(const vec_u64 a, const vec_u64 b)
+{
+#if defined(__clang__)
+ /* Clang uses a different name */
+ return __builtin_altivec_crypto_vpmsumd(a, b);
+#elif (__GNUC__ >= 10) || (__GNUC__ == 9 && __GNUC_MINOR__ >= 3) || \
+ (__GNUC__ == 8 && __GNUC_MINOR__ >= 4) || \
+ (__GNUC__ == 7 && __GNUC_MINOR__ >= 5)
+ /* GCC versions not affected by https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91275 */
+ return __builtin_crypto_vpmsumd(a, b);
+#else
+ /* GCC versions where this builtin is buggy */
+ vec_u64 vr;
+ __asm("vpmsumd %0, %1, %2"
+ : "=v"(vr)
+ : "v"(a), "v"(b));
+ return vr;
+#endif
+}
+
+SECStatus
+gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
+ unsigned int count)
+{
+ const vec_u8 leftshift = vec_splat_u8(1);
+ const vec_u64 onebit = (vec_u64){ 1, 0 };
+ const unsigned long long pd = 0xc2LLU << 56;
+
+ vec_u64 ci, v, r0, r1;
+ vec_u64 hibit;
+ unsigned i;
+
+ ci = ghash->x;
+
+ for (i = 0; i < count; i++, buf += 16) {
+ /* clang needs the following cast away from const; maybe a bug in 7.0.0 */
+ v = (vec_u64)vec_xl_be(0, (unsigned char *)buf);
+ ci ^= v;
+
+ /* Do binary mult ghash->X = C * ghash->H (Karatsuba). */
+ r0 = vpmsumd((vec_u64){ ci[0], 0 }, (vec_u64){ ghash->h[0], 0 });
+ r1 = vpmsumd((vec_u64){ ci[1], 0 }, (vec_u64){ ghash->h[1], 0 });
+ v = (vec_u64){ ci[0] ^ ci[1], ghash->h[0] ^ ghash->h[1] };
+ v = vpmsumd((vec_u64){ v[0], 0 }, (vec_u64){ v[1], 0 });
+ v ^= r0;
+ v ^= r1;
+ r0 ^= (vec_u64){ 0, v[0] };
+ r1 ^= (vec_u64){ v[1], 0 };
+
+ /* Shift one (multiply by x) as gcm spec is stupid. */
+ hibit = (vec_u64)vec_splat((vec_u8)r0, 15);
+ hibit = (vec_u64)vec_rl((vec_u8)hibit, leftshift);
+ hibit &= onebit;
+ r0 = vec_sll(r0, leftshift);
+ r1 = vec_sll(r1, leftshift);
+ r1 |= hibit;
+
+ /* Reduce */
+ v = vpmsumd((vec_u64){ r0[0], 0 }, (vec_u64){ pd, 0 });
+ r0 ^= (vec_u64){ 0, v[0] };
+ r1 ^= (vec_u64){ v[1], 0 };
+ v = vpmsumd((vec_u64){ r0[1], 0 }, (vec_u64){ pd, 0 });
+ r1 ^= v;
+ ci = r0 ^ r1;
+ }
+
+ ghash->x = ci;
+
+ return SECSuccess;
+}
+
+SECStatus
+gcm_HashInit_hw(gcmHashContext *ghash)
+{
+ ghash->x = (vec_u64)vec_splat_u32(0);
+ ghash->h = (vec_u64){ ghash->h_low, ghash->h_high };
+ ghash->ghash_mul = gcm_HashMult_hw;
+ ghash->hw = PR_TRUE;
+ return SECSuccess;
+}
+
+SECStatus
+gcm_HashZeroX_hw(gcmHashContext *ghash)
+{
+ ghash->x = (vec_u64)vec_splat_u32(0);
+ return SECSuccess;
+}
+
+#endif /* defined(USE_PPC_CRYPTO) */
diff --git a/security/nss/lib/freebl/gcm.c b/security/nss/lib/freebl/gcm.c
index e93970b88..737252eec 100644
--- a/security/nss/lib/freebl/gcm.c
+++ b/security/nss/lib/freebl/gcm.c
@@ -17,6 +17,12 @@
#include <limits.h>
+/* old gcc doesn't support some poly64x2_t intrinsic */
+#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
+ (defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
+#define USE_ARM_GCM
+#endif
+
/* Forward declarations */
SECStatus gcm_HashInit_hw(gcmHashContext *ghash);
SECStatus gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf);
@@ -30,7 +36,7 @@ SECStatus gcm_HashMult_sftw32(gcmHashContext *ghash, const unsigned char *buf,
/* Stub definitions for the above *_hw functions, which shouldn't be
* used unless NSS_X86_OR_X64 is defined */
-#ifndef NSS_X86_OR_X64
+#if !defined(NSS_X86_OR_X64) && !defined(USE_ARM_GCM) && !defined(USE_PPC_CRYPTO)
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
@@ -59,7 +65,7 @@ gcm_HashZeroX_hw(gcmHashContext *ghash)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
-#endif /* NSS_X86_OR_X64 */
+#endif /* !NSS_X86_OR_X64 && !USE_ARM_GCM && !USE_PPC_CRYPTO */
uint64_t
get64(const unsigned char *bytes)
@@ -86,7 +92,13 @@ gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H, PRBool sw)
ghash->h_low = get64(H + 8);
ghash->h_high = get64(H);
+#ifdef USE_ARM_GCM
+ if (arm_pmull_support() && !sw) {
+#elif defined(USE_PPC_CRYPTO)
+ if (ppc_crypto_support() && !sw) {
+#else
if (clmul_support() && !sw) {
+#endif
rv = gcm_HashInit_hw(ghash);
} else {
/* We fall back to the software implementation if we can't use / don't
@@ -531,6 +543,15 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
+
+ if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
+ gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
+ gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
+ gcmParams->ulTagBits != 32) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
gcm = PORT_ZNew(GCMContext);
if (gcm == NULL) {
return NULL;
diff --git a/security/nss/lib/freebl/gcm.h b/security/nss/lib/freebl/gcm.h
index 42ef0f717..571b9ec55 100644
--- a/security/nss/lib/freebl/gcm.h
+++ b/security/nss/lib/freebl/gcm.h
@@ -26,6 +26,32 @@
#endif /* NSS_DISABLE_SSE2 */
#endif
+#ifdef __aarch64__
+#include <arm_neon.h>
+#endif
+
+#ifdef __powerpc64__
+#include "altivec-types.h"
+
+/* The ghash freebl test tries to use this in C++, and gcc defines conflict. */
+#ifdef __cplusplus
+#undef pixel
+#undef vector
+#undef bool
+#endif
+
+/*
+ * PPC CRYPTO requires at least gcc 5 or clang. The LE check is purely
+ * because it's only been tested on LE. If you're interested in BE,
+ * please send a patch.
+ */
+#if (defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 5)) && \
+ defined(IS_LITTLE_ENDIAN)
+#define USE_PPC_CRYPTO
+#endif
+
+#endif
+
SEC_BEGIN_PROTOS
#ifdef HAVE_INT128_SUPPORT
@@ -61,6 +87,10 @@ typedef SECStatus (*ghash_t)(gcmHashContext *, const unsigned char *,
pre_align struct gcmHashContextStr {
#ifdef NSS_X86_OR_X64
__m128i x, h;
+#elif defined(__aarch64__)
+ uint64x2_t x, h;
+#elif defined(USE_PPC_CRYPTO)
+ vec_u64 x, h;
#endif
uint64_t x_low, x_high, h_high, h_low;
unsigned char buffer[MAX_BLOCK_SIZE];
diff --git a/security/nss/lib/freebl/intel-aes.h b/security/nss/lib/freebl/intel-aes.h
index d5bd2d8ca..e7fe1a03b 100644
--- a/security/nss/lib/freebl/intel-aes.h
+++ b/security/nss/lib/freebl/intel-aes.h
@@ -100,7 +100,7 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
unsigned int inputLen,
unsigned int blocksize);
-#define intel_aes_ecb_worker(encrypt, keysize) \
+#define native_aes_ecb_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? intel_aes_encrypt_ecb_128 \
: (keysize) == 24 ? intel_aes_encrypt_ecb_192 \
@@ -109,7 +109,7 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
: (keysize) == 24 ? intel_aes_decrypt_ecb_192 \
: intel_aes_decrypt_ecb_256))
-#define intel_aes_cbc_worker(encrypt, keysize) \
+#define native_aes_cbc_worker(encrypt, keysize) \
((encrypt) \
? ((keysize) == 16 ? intel_aes_encrypt_cbc_128 \
: (keysize) == 24 ? intel_aes_encrypt_cbc_192 \
@@ -123,21 +123,21 @@ SECStatus intel_aes_encrypt_ctr_256(CTRContext *cx, unsigned char *output,
: (nr) == 12 ? intel_aes_encrypt_ctr_192 \
: intel_aes_encrypt_ctr_256)
-#define intel_aes_init(encrypt, keysize) \
- do { \
- if (encrypt) { \
- if (keysize == 16) \
- intel_aes_encrypt_init_128(key, cx->expandedKey); \
- else if (keysize == 24) \
- intel_aes_encrypt_init_192(key, cx->expandedKey); \
- else \
- intel_aes_encrypt_init_256(key, cx->expandedKey); \
- } else { \
- if (keysize == 16) \
- intel_aes_decrypt_init_128(key, cx->expandedKey); \
- else if (keysize == 24) \
- intel_aes_decrypt_init_192(key, cx->expandedKey); \
- else \
- intel_aes_decrypt_init_256(key, cx->expandedKey); \
- } \
+#define native_aes_init(encrypt, keysize) \
+ do { \
+ if (encrypt) { \
+ if (keysize == 16) \
+ intel_aes_encrypt_init_128(key, cx->k.expandedKey); \
+ else if (keysize == 24) \
+ intel_aes_encrypt_init_192(key, cx->k.expandedKey); \
+ else \
+ intel_aes_encrypt_init_256(key, cx->k.expandedKey); \
+ } else { \
+ if (keysize == 16) \
+ intel_aes_decrypt_init_128(key, cx->k.expandedKey); \
+ else if (keysize == 24) \
+ intel_aes_decrypt_init_192(key, cx->k.expandedKey); \
+ else \
+ intel_aes_decrypt_init_256(key, cx->k.expandedKey); \
+ } \
} while (0)
diff --git a/security/nss/lib/freebl/intel-gcm-wrap.c b/security/nss/lib/freebl/intel-gcm-wrap.c
index f69bc7c7a..059fc6332 100644
--- a/security/nss/lib/freebl/intel-gcm-wrap.c
+++ b/security/nss/lib/freebl/intel-gcm-wrap.c
@@ -62,6 +62,15 @@ intel_AES_GCM_CreateContext(void *context,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
+
+ if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
+ gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
+ gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
+ gcmParams->ulTagBits != 32) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
// Limit AADLen in accordance with SP800-38D
if (sizeof(AAD_whole_len) >= 8 && AAD_whole_len > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
@@ -80,7 +89,7 @@ intel_AES_GCM_CreateContext(void *context,
gcm->Mlen = 0;
/* first prepare H and its derivatives for ghash */
- intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->expandedKey, aes->Nr);
+ intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->k.expandedKey, aes->Nr);
/* Initial TAG value is zero */
_mm_storeu_si128((__m128i *)gcm->T, _mm_setzero_si128());
@@ -149,6 +158,7 @@ loser:
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
+ PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
diff --git a/security/nss/lib/freebl/ldvector.c b/security/nss/lib/freebl/ldvector.c
index d39965256..6ae9ef68d 100644
--- a/security/nss/lib/freebl/ldvector.c
+++ b/security/nss/lib/freebl/ldvector.c
@@ -10,6 +10,7 @@ extern int FREEBL_InitStubs(void);
#endif
#include "loader.h"
+#include "cmac.h"
#include "alghmac.h"
#include "hmacct.h"
#include "blapii.h"
@@ -313,10 +314,22 @@ static const struct FREEBLVectorStr vector =
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
- BLAKE2B_Resurrect
+ BLAKE2B_Resurrect,
/* End of Version 3.020 */
+ ChaCha20_Xor,
+
+ /* End of version 3.021 */
+
+ CMAC_Init,
+ CMAC_Create,
+ CMAC_Begin,
+ CMAC_Update,
+ CMAC_Finish,
+ CMAC_Destroy
+
+ /* End of version 3.022 */
};
const FREEBLVector*
diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c
index 6d200e6dd..945ecf171 100644
--- a/security/nss/lib/freebl/loader.c
+++ b/security/nss/lib/freebl/loader.c
@@ -2061,6 +2061,16 @@ EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
}
SECStatus
+ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len,
+ const unsigned char *k, const unsigned char *nonce, PRUint32 ctr)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) {
+ return SECFailure;
+ }
+ return (vector->p_ChaCha20_Xor)(output, block, len, k, nonce, ctr);
+}
+
+SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
const unsigned char *key, unsigned int keyLen,
unsigned int tagLen)
@@ -2235,3 +2245,54 @@ BLAKE2B_Resurrect(unsigned char *space, void *arg)
}
return (vector->p_BLAKE2B_Resurrect)(space, arg);
}
+
+/* == New for CMAC == */
+SECStatus
+CMAC_Init(CMACContext *ctx, CMACCipher type, const unsigned char *key,
+ unsigned int key_len)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return SECFailure;
+ return (vector->p_CMAC_Init)(ctx, type, key, key_len);
+}
+
+CMACContext *
+CMAC_Create(CMACCipher type, const unsigned char *key, unsigned int key_len)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return NULL;
+ return (vector->p_CMAC_Create)(type, key, key_len);
+}
+
+SECStatus
+CMAC_Begin(CMACContext *ctx)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return SECFailure;
+ return (vector->p_CMAC_Begin)(ctx);
+}
+
+SECStatus
+CMAC_Update(CMACContext *ctx, const unsigned char *data, unsigned int data_len)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return SECFailure;
+ return (vector->p_CMAC_Update)(ctx, data, data_len);
+}
+
+SECStatus
+CMAC_Finish(CMACContext *ctx, unsigned char *result, unsigned int *result_len,
+ unsigned int max_result_len)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return SECFailure;
+ return (vector->p_CMAC_Finish)(ctx, result, result_len, max_result_len);
+}
+
+void
+CMAC_Destroy(CMACContext *ctx, PRBool free_it)
+{
+ if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
+ return;
+ (vector->p_CMAC_Destroy)(ctx, free_it);
+}
diff --git a/security/nss/lib/freebl/loader.h b/security/nss/lib/freebl/loader.h
index ff10cf9ba..ff1a5d1a4 100644
--- a/security/nss/lib/freebl/loader.h
+++ b/security/nss/lib/freebl/loader.h
@@ -10,7 +10,7 @@
#include "blapi.h"
-#define FREEBL_VERSION 0x0314
+#define FREEBL_VERSION 0x0316
struct FREEBLVectorStr {
@@ -759,6 +759,26 @@ struct FREEBLVectorStr {
/* Version 3.020 came to here */
+ SECStatus (*p_ChaCha20_Xor)(unsigned char *output, const unsigned char *block,
+ unsigned int len, const unsigned char *k,
+ const unsigned char *nonce, PRUint32 ctr);
+
+ /* Version 3.021 came to here */
+
+ SECStatus (*p_CMAC_Init)(CMACContext *ctx, CMACCipher type,
+ const unsigned char *key, unsigned int key_len);
+ CMACContext *(*p_CMAC_Create)(CMACCipher type, const unsigned char *key,
+ unsigned int key_len);
+ SECStatus (*p_CMAC_Begin)(CMACContext *ctx);
+ SECStatus (*p_CMAC_Update)(CMACContext *ctx, const unsigned char *data,
+ unsigned int data_len);
+ SECStatus (*p_CMAC_Finish)(CMACContext *ctx, unsigned char *result,
+ unsigned int *result_len,
+ unsigned int max_result_len);
+ void (*p_CMAC_Destroy)(CMACContext *ctx, PRBool free_it);
+
+ /* Version 3.022 came to here */
+
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
};
diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn
index e4c9ab0b7..8915ac474 100644
--- a/security/nss/lib/freebl/manifest.mn
+++ b/security/nss/lib/freebl/manifest.mn
@@ -85,6 +85,7 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
+ cmac.h \
alghmac.h \
blake2b.h \
blapi.h \
@@ -119,6 +120,7 @@ CSRCS = \
md2.c \
md5.c \
sha512.c \
+ cmac.c \
alghmac.c \
rawhash.c \
alg2268.c \
@@ -162,6 +164,7 @@ CSRCS = \
ALL_CSRCS := $(CSRCS)
ALL_HDRS = \
+ cmac.h \
alghmac.h \
blake2b.h \
blapi.h \
diff --git a/security/nss/lib/freebl/mpi/README b/security/nss/lib/freebl/mpi/README
index cf4302758..a49aa9d8d 100644
--- a/security/nss/lib/freebl/mpi/README
+++ b/security/nss/lib/freebl/mpi/README
@@ -167,6 +167,7 @@ To set an mp_int to a given value, the following functions are given:
mp_set(mp_int *mp, mp_digit d);
mp_set_int(mp_int *mp, long z);
+ mp_set_ulong(mp_int *mp, unsigned long z);
The mp_set() function sets the mp_int to a single digit value, while
mp_set_int() sets the mp_int to a signed long integer value.
diff --git a/security/nss/lib/freebl/mpi/mpcpucache.c b/security/nss/lib/freebl/mpi/mpcpucache.c
index 336b4cc55..2ad291fab 100644
--- a/security/nss/lib/freebl/mpi/mpcpucache.c
+++ b/security/nss/lib/freebl/mpi/mpcpucache.c
@@ -727,7 +727,7 @@ static inline void
dcbzl(char *array)
{
register char *a asm("r2") = array;
- __asm__ __volatile__("dcbzl %0,r0"
+ __asm__ __volatile__("dcbzl %0,0"
: "=r"(a)
: "0"(a));
}
diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c
index 401eac51d..7e96e51ff 100644
--- a/security/nss/lib/freebl/mpi/mpi.c
+++ b/security/nss/lib/freebl/mpi/mpi.c
@@ -341,33 +341,21 @@ mp_set(mp_int *mp, mp_digit d)
mp_err
mp_set_int(mp_int *mp, long z)
{
- int ix;
unsigned long v = labs(z);
mp_err res;
ARGCHK(mp != NULL, MP_BADARG);
- mp_zero(mp);
- if (z == 0)
- return MP_OKAY; /* shortcut for zero */
-
- if (sizeof v <= sizeof(mp_digit)) {
- DIGIT(mp, 0) = v;
- } else {
- for (ix = sizeof(long) - 1; ix >= 0; ix--) {
- if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
- return res;
-
- res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
- if (res != MP_OKAY)
- return res;
- }
+ /* https://bugzilla.mozilla.org/show_bug.cgi?id=1509432 */
+ if ((res = mp_set_ulong(mp, v)) != MP_OKAY) { /* avoids duplicated code */
+ return res;
}
- if (z < 0)
+
+ if (z < 0) {
SIGN(mp) = NEG;
+ }
return MP_OKAY;
-
} /* end mp_set_int() */
/* }}} */
@@ -1441,7 +1429,7 @@ s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
mp_digit d;
unsigned int dig, bit;
- ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+ ARGCHK(a != NULL && b != NULL && c != NULL && m != NULL, MP_BADARG);
if (mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
return MP_RANGE;
@@ -1528,7 +1516,7 @@ mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
mp_int s, x;
mp_err res;
- ARGCHK(a != NULL && c != NULL, MP_BADARG);
+ ARGCHK(a != NULL && c != NULL && m != NULL, MP_BADARG);
if ((res = mp_init(&s)) != MP_OKAY)
return res;
@@ -1581,6 +1569,8 @@ X:
int
mp_cmp_z(const mp_int *a)
{
+ ARGMPCHK(a != NULL);
+
if (SIGN(a) == NEG)
return MP_LT;
else if (USED(a) == 1 && DIGIT(a, 0) == 0)
@@ -1671,7 +1661,7 @@ mp_cmp_mag(const mp_int *a, const mp_int *b)
int
mp_isodd(const mp_int *a)
{
- ARGCHK(a != NULL, 0);
+ ARGMPCHK(a != NULL);
return (int)(DIGIT(a, 0) & 1);
@@ -2015,7 +2005,7 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
mp_err k = 0;
mp_int d, f, g;
- ARGCHK(a && p && c, MP_BADARG);
+ ARGCHK(a != NULL && p != NULL && c != NULL, MP_BADARG);
MP_DIGITS(&d) = 0;
MP_DIGITS(&f) = 0;
@@ -2063,7 +2053,10 @@ s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
}
}
if (res >= 0) {
- while (MP_SIGN(c) != MP_ZPOS) {
+ if (mp_cmp_mag(c, p) >= 0) {
+ MP_CHECKOK(mp_div(c, p, NULL, c));
+ }
+ if (MP_SIGN(c) != MP_ZPOS) {
MP_CHECKOK(mp_add(c, p, c));
}
res = k;
@@ -2146,7 +2139,7 @@ s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
mp_err res;
mp_int x;
- ARGCHK(a && m && c, MP_BADARG);
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@@ -2184,7 +2177,7 @@ mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
mp_int g, x;
mp_err res;
- ARGCHK(a && m && c, MP_BADARG);
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@@ -2280,6 +2273,8 @@ s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
mp_int oddPart, evenPart; /* parts to combine via CRT. */
mp_int C2, tmp1, tmp2;
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
/*static const mp_digit d1 = 1; */
/*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
@@ -2358,8 +2353,7 @@ CLEANUP:
mp_err
mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
{
-
- ARGCHK(a && m && c, MP_BADARG);
+ ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
if (mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
return MP_RANGE;
@@ -2726,6 +2720,8 @@ mp_strerror(mp_err ec)
mp_err
s_mp_grow(mp_int *mp, mp_size min)
{
+ ARGCHK(mp != NULL, MP_BADARG);
+
if (min > ALLOC(mp)) {
mp_digit *tmp;
@@ -2755,6 +2751,8 @@ s_mp_grow(mp_int *mp, mp_size min)
mp_err
s_mp_pad(mp_int *mp, mp_size min)
{
+ ARGCHK(mp != NULL, MP_BADARG);
+
if (min > USED(mp)) {
mp_err res;
@@ -2874,6 +2872,8 @@ s_mp_lshd(mp_int *mp, mp_size p)
mp_err res;
unsigned int ix;
+ ARGCHK(mp != NULL, MP_BADARG);
+
if (p == 0)
return MP_OKAY;
@@ -3006,6 +3006,8 @@ s_mp_mul_2(mp_int *mp)
unsigned int ix, used;
mp_digit kin = 0;
+ ARGCHK(mp != NULL, MP_BADARG);
+
/* Shift digits leftward by 1 bit */
used = MP_USED(mp);
pd = MP_DIGITS(mp);
@@ -3115,6 +3117,8 @@ s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
mp_digit b_msd;
mp_err res = MP_OKAY;
+ ARGCHK(a != NULL && b != NULL && pd != NULL, MP_BADARG);
+
d = 0;
mask = DIGIT_MAX & ~(DIGIT_MAX >> 1); /* mask is msb of digit */
b_msd = DIGIT(b, USED(b) - 1);
@@ -4379,6 +4383,8 @@ CLEANUP:
int
s_mp_cmp(const mp_int *a, const mp_int *b)
{
+ ARGMPCHK(a != NULL && b != NULL);
+
mp_size used_a = MP_USED(a);
{
mp_size used_b = MP_USED(b);
@@ -4430,6 +4436,8 @@ IS_GT:
int
s_mp_cmp_d(const mp_int *a, mp_digit d)
{
+ ARGMPCHK(a != NULL);
+
if (USED(a) > 1)
return MP_GT;
@@ -4456,6 +4464,8 @@ s_mp_ispow2(const mp_int *v)
mp_digit d;
int extra = 0, ix;
+ ARGMPCHK(v != NULL);
+
ix = MP_USED(v) - 1;
d = MP_DIGIT(v, ix); /* most significant digit of v */
@@ -4783,10 +4793,7 @@ mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
int ix, jx;
unsigned int bytes;
- ARGCHK(mp != NULL, MP_BADARG);
- ARGCHK(str != NULL, MP_BADARG);
- ARGCHK(!SIGN(mp), MP_BADARG);
- ARGCHK(length > 0, MP_BADARG);
+ ARGCHK(mp != NULL && str != NULL && !SIGN(mp) && length > 0, MP_BADARG);
/* Constant time on the value of mp. Don't use mp_unsigned_octet_size. */
bytes = USED(mp) * MP_DIGIT_SIZE;
diff --git a/security/nss/lib/freebl/mpi/mpi.h b/security/nss/lib/freebl/mpi/mpi.h
index d5aef46d7..af608b43d 100644
--- a/security/nss/lib/freebl/mpi/mpi.h
+++ b/security/nss/lib/freebl/mpi/mpi.h
@@ -288,7 +288,14 @@ void freebl_cpuid(unsigned long op, unsigned long *eax,
#define DIGITS(MP) MP_DIGITS(MP)
#define DIGIT(MP, N) MP_DIGIT(MP, N)
+/* Functions which return an mp_err value will NULL-check their arguments via
+ * ARGCHK(condition, return), where the caller is responsible for checking the
+ * mp_err return code. For functions that return an integer type, the caller
+ * has no way to tell if the value is an error code or a legitimate value.
+ * Therefore, ARGMPCHK(condition) will trigger an assertion failure on debug
+ * builds, but no-op in optimized builds. */
#if MP_ARGCHK == 1
+#define ARGMPCHK(X) /* */
#define ARGCHK(X, Y) \
{ \
if (!(X)) { \
@@ -297,9 +304,11 @@ void freebl_cpuid(unsigned long op, unsigned long *eax,
}
#elif MP_ARGCHK == 2
#include <assert.h>
+#define ARGMPCHK(X) assert(X)
#define ARGCHK(X, Y) assert(X)
#else
-#define ARGCHK(X, Y) /* */
+#define ARGMPCHK(X) /* */
+#define ARGCHK(X, Y) /* */
#endif
#ifdef CT_VERIF
diff --git a/security/nss/lib/freebl/pqg.c b/security/nss/lib/freebl/pqg.c
index 2f24afd24..626b2fb85 100644
--- a/security/nss/lib/freebl/pqg.c
+++ b/security/nss/lib/freebl/pqg.c
@@ -491,11 +491,11 @@ cleanup:
** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
** steps 16 through 34 of FIPS 186-2 C.6
*/
-#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
static SECStatus
makePrimefromPrimesShaweTaylor(
HASH_HashType hashtype, /* selected Hashing algorithm */
unsigned int length, /* input. Length of prime in bits. */
+ unsigned int seedlen, /* input seed length in bits */
mp_int *c0, /* seed prime */
mp_int *q, /* sub prime, can be 1 */
mp_int *prime, /* output. */
@@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor(
old_counter = *prime_gen_counter;
/*
** Comment: Generate a pseudorandom integer x in the interval
- ** [2**(lenght-1), 2**length].
+ ** [2**(length-1), 2**length].
**
** Step 6/18 x = 0
*/
@@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor(
for (i = 0; i < iterations; i++) {
/* is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
- MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
+ seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 8/20 prime_seed = prime_seed + iterations + 1 */
- CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
- prime_seed));
+ CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/*
** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
**
@@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor(
x[offset] = (mask & x[offset]) | bit;
/*
** Comment: Generate a candidate prime c in the interval
- ** [2**(lenght-1), 2**length].
+ ** [2**(length-1), 2**length].
**
** Step 10 t = ceiling(x/(2q(p0)))
** Step 22 t = ceiling(x/(2(c0)))
@@ -624,7 +623,7 @@ step_23:
/* t = 2**(length-1) + 2qc0 -1 */
CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
/* t = floor((2**(length-1)+2qc0 -1)/2qco)
- * = ceil(2**(lenght-2)/2qc0) */
+ * = ceil(2**(length-2)/2qc0) */
CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
@@ -645,13 +644,11 @@ step_23:
** NOTE: we reuse the x array for 'a' initially.
*/
for (i = 0; i < iterations; i++) {
- /* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
- MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
+ seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 16/28 prime_seed = prime_seed + iterations + 1 */
- CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
- prime_seed));
+ CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/* Step 17/29 a = 2 + (a mod (c-3)). */
CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
@@ -742,6 +739,7 @@ makePrimefromSeedShaweTaylor(
int hashlen = HASH_ResultLen(hashtype);
int outlen = hashlen * PR_BITS_PER_BYTE;
int offset;
+ int seedlen = input_seed->len * 8; /*seedlen is in bits */
unsigned char bit, mask;
unsigned char x[HASH_LENGTH_MAX * 2];
mp_digit dummy;
@@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor(
goto cleanup;
}
/* Steps 16-34 */
- rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
+ rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
prime, prime_seed, prime_gen_counter);
goto cleanup; /* we're done, one way or the other */
}
@@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor(
step_5:
/* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
- CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
- MAX_ST_SEED_BITS, &x[hashlen]));
+ CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
for (i = 0; i < hashlen; i++) {
x[i] = x[i] ^ x[i + hashlen];
}
@@ -817,7 +814,7 @@ step_5:
/* Step 8 prime_gen_counter = prime_gen_counter + 1 */
(*prime_gen_counter)++;
/* Step 9 prime_seed = prime_seed + 2 */
- CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
+ CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
/* Step 10 Perform deterministic primality test on c. For example, since
** c is small, it's primality can be tested by trial division, See
** See Appendic C.7.
@@ -890,9 +887,10 @@ findQfromSeed(
mp_int *Q_, /* output. */
unsigned int *qseed_len, /* output */
HASH_HashType *hashtypePtr, /* output. Hash uses */
- pqgGenType *typePtr) /* output. Generation Type used */
+ pqgGenType *typePtr, /* output. Generation Type used */
+ unsigned int *qgen_counter) /* output. q_counter */
{
- HASH_HashType hashtype;
+ HASH_HashType hashtype = HASH_AlgNULL;
SECItem firstseed = { 0, 0, 0 };
SECItem qseed = { 0, 0, 0 };
SECStatus rv;
@@ -964,6 +962,7 @@ findQfromSeed(
*qseed_len = qseed.len;
*hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE;
+ *qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE);
return SECSuccess;
}
@@ -1015,6 +1014,8 @@ makePfromQandSeed(
hashlen = HASH_ResultLen(hashtype);
outlen = hashlen * PR_BITS_PER_BYTE;
+ PORT_Assert(outlen > 0);
+
/* L - 1 = n*outlen + b */
n = (L - 1) / outlen;
b = (L - 1) % outlen;
@@ -1238,7 +1239,7 @@ pqg_ParamGen(unsigned int L, unsigned int N, pqgGenType type,
unsigned int offset; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
unsigned int outlen; /* Per FIPS 186-3, appendix A.1.1.2. */
unsigned int maxCount;
- HASH_HashType hashtype;
+ HASH_HashType hashtype = HASH_AlgNULL;
SECItem *seed; /* Per FIPS 186, app 2.2. 186-3 app A.1.1.2 */
PLArenaPool *arena = NULL;
PQGParams *params = NULL;
@@ -1388,19 +1389,26 @@ step_5:
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed, &pgen_counter));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
- CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
+ CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
&p0, &Q, &P, &pseed, &pgen_counter));
/* combine all the seeds */
- seed->len = firstseed.len + qseed.len + pseed.len;
+ if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
+ goto cleanup;
+ }
+ /* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps.
+ * we want to make sure those are added back in so the individual seed lengths are predictable from
+ * the overall seed length */
+ seed->len = firstseed.len * 3;
seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
if (seed->data == NULL) {
goto cleanup;
}
PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
- PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
- PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
- counter = 0; /* (qgen_counter << 16) | pgen_counter; */
+ PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
+ PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
+ counter = (qgen_counter << 16) | pgen_counter;
/* we've generated both P and Q now, skip to generating G */
goto generate_G;
@@ -1620,9 +1628,10 @@ PQG_VerifyParams(const PQGParams *params,
int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */
unsigned int qseed_len;
+ unsigned int qgen_counter_ = 0;
SECItem pseed_ = { 0, 0, 0 };
- HASH_HashType hashtype;
- pqgGenType type;
+ HASH_HashType hashtype = HASH_AlgNULL;
+ pqgGenType type = FIPS186_1_TYPE;
#define CHECKPARAM(cond) \
if (!(cond)) { \
@@ -1699,48 +1708,55 @@ PQG_VerifyParams(const PQGParams *params,
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */
/* 7. counter < 4*L */
- CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
/* 8. g >= N and g < 2*L (g is length of seed in bits) */
- g = vfy->seed.len * 8;
- CHECKPARAM(g >= N && g < counter_max / 2);
+ /* step 7 and 8 are delayed until we determine which type of generation
+ * was used */
/* 9. Q generated from SEED matches Q in PQGParams. */
/* This function checks all possible hash and generation types to
* find a Q_ which matches Q. */
+ g = vfy->seed.len * 8;
CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
- &hashtype, &type) == SECSuccess);
+ &hashtype, &type, &qgen_counter_) == SECSuccess);
CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
+ /* now we can do steps 7 & 8*/
+ if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
+ CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
+ CHECKPARAM(g >= N && g < counter_max / 2);
+ }
if (type == FIPS186_3_ST_TYPE) {
SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 };
unsigned int first_seed_len;
- unsigned int pgen_counter = 0;
+ unsigned int pgen_counter_ = 0;
+ unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
+ unsigned int pgen_counter = (vfy->counter) & 0xffff;
/* extract pseed and qseed from domain_parameter_seed, which is
* first_seed || pseed || qseed. qseed is first_seed + small_integer
- * pseed is qseed + small_integer. This means most of the time
+ * mod the length of first_seed. pseed is qseed + small_integer mod
+ * the length of first_seed. This means most of the time
* first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
- * pseed.len will be one greater than first_seed.len, so we can
- * depend on the fact that
- * first_seed.len = floor(domain_parameter_seed.len/3).
- * findQfromSeed returned qseed.len, so we can calculate pseed.len as
- * pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
- * this is probably over kill, since 99.999% of the time they will all
- * be equal.
- *
- * With the lengths, we can now find the offsets;
+ * pseed.len will be smaller because mpi clamps them. pqgGen
+ * automatically adds the zero pad back though, so we can depend
+ * domain_parameter_seed.len to be a multiple of three. We only have
+ * to deal with the fact that the returned seeds from our functions
+ * could be shorter.
+ * first_seed.len = domain_parameter_seed.len/3
+ * We can now find the offsets;
* first_seed.data = domain_parameter_seed.data + 0
* pseed.data = domain_parameter_seed.data + first_seed.len
* qseed.data = domain_parameter_seed.data
* + domain_paramter_seed.len - qseed.len
- *
+ * We deal with pseed possibly having zero pad in the pseed check later.
*/
first_seed_len = vfy->seed.len / 3;
CHECKPARAM(qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 > N - 1);
- CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
+ CHECKPARAM(first_seed_len * 8 < counter_max / 2);
+ CHECKPARAM(first_seed_len >= qseed_len);
qseed.len = qseed_len;
qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
- pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
+ pseed.len = first_seed_len;
pseed.data = vfy->seed.data + first_seed_len;
/*
@@ -1752,14 +1768,34 @@ PQG_VerifyParams(const PQGParams *params,
** (ST_Random_Prime((ceil(length/2)+1, input_seed)
*/
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
- &qseed, &p0, &pseed_, &pgen_counter));
+ &qseed, &p0, &pseed_, &pgen_counter_));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
- CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
- &p0, &Q_, &P_, &pseed_, &pgen_counter));
+ CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
+ &p0, &Q_, &P_, &pseed_, &pgen_counter_));
CHECKPARAM(mp_cmp(&P, &P_) == 0);
/* make sure pseed wasn't tampered with (since it is part of
* calculating G) */
+ if (pseed.len > pseed_.len) {
+ /* handle the case of zero pad for pseed */
+ int extra = pseed.len - pseed_.len;
+ int i;
+ for (i = 0; i < extra; i++) {
+ if (pseed.data[i] != 0) {
+ *result = SECFailure;
+ goto cleanup;
+ }
+ }
+ pseed.data += extra;
+ pseed.len -= extra;
+ /* the rest is handled in the normal compare below */
+ }
CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
+ if (vfy->counter != -1) {
+ CHECKPARAM(pgen_counter < counter_max);
+ CHECKPARAM(qgen_counter < counter_max);
+ CHECKPARAM((pgen_counter_ == pgen_counter));
+ CHECKPARAM((qgen_counter_ == qgen_counter));
+ }
} else if (vfy->counter == -1) {
/* If counter is set to -1, we are really only verifying G, skip
* the remainder of the checks for P */
@@ -1768,6 +1804,7 @@ PQG_VerifyParams(const PQGParams *params,
/* 10. P generated from (L, counter, g, SEED, Q) matches P
* in PQGParams. */
outlen = HASH_ResultLen(hashtype) * PR_BITS_PER_BYTE;
+ PORT_Assert(outlen > 0);
n = (L - 1) / outlen;
offset = vfy->counter * (n + 1) + ((type == FIPS186_1_TYPE) ? 2 : 1);
CHECK_SEC_OK(makePfromQandSeed(hashtype, L, N, offset, g, &vfy->seed,
diff --git a/security/nss/lib/freebl/rijndael.c b/security/nss/lib/freebl/rijndael.c
index 5de27de9c..fbf229aa5 100644
--- a/security/nss/lib/freebl/rijndael.c
+++ b/security/nss/lib/freebl/rijndael.c
@@ -20,9 +20,19 @@
#include "gcm.h"
#include "mpi.h"
+#if (!defined(IS_LITTLE_ENDIAN) && !defined(NSS_X86_OR_X64)) || \
+ (defined(__arm__) && !defined(__ARM_NEON) && !defined(__ARM_NEON__))
+// not test yet on big endian platform of arm
+#undef USE_HW_AES
+#endif
+
#ifdef USE_HW_AES
+#ifdef NSS_X86_OR_X64
#include "intel-aes.h"
+#else
+#include "aes-armv8.h"
#endif
+#endif /* USE_HW_AES */
#ifdef INTEL_GCM
#include "intel-gcm.h"
#endif /* INTEL_GCM */
@@ -321,7 +331,7 @@ rijndael_key_expansion7(AESContext *cx, const unsigned char *key, unsigned int N
PRUint32 *W;
PRUint32 *pW;
PRUint32 tmp;
- W = cx->expandedKey;
+ W = cx->k.expandedKey;
/* 1. the first Nk words contain the cipher key */
memcpy(W, key, Nk * 4);
i = Nk;
@@ -353,7 +363,7 @@ rijndael_key_expansion(AESContext *cx, const unsigned char *key, unsigned int Nk
rijndael_key_expansion7(cx, key, Nk);
return;
}
- W = cx->expandedKey;
+ W = cx->k.expandedKey;
/* The first Nk words contain the input cipher key */
memcpy(W, key, Nk * 4);
i = Nk;
@@ -430,7 +440,7 @@ rijndael_invkey_expansion(AESContext *cx, const unsigned char *key, unsigned int
/* ... but has the additional step of InvMixColumn,
* excepting the first and last round keys.
*/
- roundkeyw = cx->expandedKey + cx->Nb;
+ roundkeyw = cx->k.expandedKey + cx->Nb;
for (r = 1; r < cx->Nr; ++r) {
/* each key word, roundkeyw, represents a column in the key
* matrix. Each column is multiplied by the InvMixColumn matrix.
@@ -528,7 +538,7 @@ rijndael_encryptBlock128(AESContext *cx,
pOut = (unsigned char *)output;
}
#endif
- roundkeyw = cx->expandedKey;
+ roundkeyw = cx->k.expandedKey;
/* Step 1: Add Round Key 0 to initial state */
COLUMN_0(state) = *((PRUint32 *)(pIn)) ^ *roundkeyw++;
COLUMN_1(state) = *((PRUint32 *)(pIn + 4)) ^ *roundkeyw++;
@@ -623,7 +633,7 @@ rijndael_decryptBlock128(AESContext *cx,
pOut = (unsigned char *)output;
}
#endif
- roundkeyw = cx->expandedKey + cx->Nb * cx->Nr + 3;
+ roundkeyw = cx->k.expandedKey + cx->Nb * cx->Nr + 3;
/* reverse the final key addition */
COLUMN_3(state) = *((PRUint32 *)(pIn + 12)) ^ *roundkeyw--;
COLUMN_2(state) = *((PRUint32 *)(pIn + 8)) ^ *roundkeyw--;
@@ -847,7 +857,11 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- use_hw_aes = aesni_support() && (keysize % 8) == 0;
+#if defined(NSS_X86_OR_X64) || defined(USE_HW_AES)
+ use_hw_aes = (aesni_support() || arm_aes_support()) && (keysize % 8) == 0;
+#else
+ use_hw_aes = PR_FALSE;
+#endif
/* Nb = (block size in bits) / 32 */
cx->Nb = AES_BLOCK_SIZE / 4;
/* Nk = (key size in bits) / 32 */
@@ -860,7 +874,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
#ifdef USE_HW_AES
if (use_hw_aes) {
cx->worker = (freeblCipherFunc)
- intel_aes_cbc_worker(encrypt, keysize);
+ native_aes_cbc_worker(encrypt, keysize);
} else
#endif
{
@@ -872,7 +886,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
#ifdef USE_HW_AES
if (use_hw_aes) {
cx->worker = (freeblCipherFunc)
- intel_aes_ecb_worker(encrypt, keysize);
+ native_aes_ecb_worker(encrypt, keysize);
} else
#endif
{
@@ -888,7 +902,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
}
#ifdef USE_HW_AES
if (use_hw_aes) {
- intel_aes_init(encrypt, keysize);
+ native_aes_init(encrypt, keysize);
} else
#endif
{
@@ -1032,13 +1046,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv,
void
AES_DestroyContext(AESContext *cx, PRBool freeit)
{
+ void *mem = cx->mem;
if (cx->worker_cx && cx->destroy) {
(*cx->destroy)(cx->worker_cx, PR_TRUE);
cx->worker_cx = NULL;
cx->destroy = NULL;
}
+ PORT_Memset(cx, 0, sizeof(AESContext));
if (freeit) {
- PORT_Free(cx->mem);
+ PORT_Free(mem);
+ } else {
+ /* if we are not freeing the context, restore mem, We may get called
+ * again to actually free the context */
+ cx->mem = mem;
}
}
diff --git a/security/nss/lib/freebl/rijndael.h b/security/nss/lib/freebl/rijndael.h
index 1b63a323d..61060e016 100644
--- a/security/nss/lib/freebl/rijndael.h
+++ b/security/nss/lib/freebl/rijndael.h
@@ -68,7 +68,7 @@ struct AESContextStr {
__m128i keySchedule[15];
#endif
PRUint32 expandedKey[RIJNDAEL_MAX_EXP_KEY_SIZE];
- };
+ } k;
unsigned int Nb;
unsigned int Nr;
freeblCipherFunc worker;
diff --git a/security/nss/lib/freebl/rsapkcs.c b/security/nss/lib/freebl/rsapkcs.c
index 6f94770ad..f26cd2954 100644
--- a/security/nss/lib/freebl/rsapkcs.c
+++ b/security/nss/lib/freebl/rsapkcs.c
@@ -141,6 +141,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
/*
* 0x00 || BT || Pad || 0x00 || ActualData
* 1 1 padLen 1 data->len
+ * padLen must be at least RSA_BLOCK_MIN_PAD_LEN (8) bytes.
* Pad is either all 0x00 or all 0xff bytes, depending on blockType.
*/
padLen = modulusLen - data->len - 3;
@@ -171,6 +172,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
* If we need more than that, refill the bytes after Pad with
* new random bytes as necessary.
*/
+
padLen = modulusLen - (data->len + 3);
PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
@@ -239,7 +241,6 @@ rsa_FormatBlock(SECItem *result,
if (data->len > (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))) {
return SECFailure;
}
-
result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
if (result->data == NULL) {
result->len = 0;
diff --git a/security/nss/lib/freebl/seed.c b/security/nss/lib/freebl/seed.c
index f198cce45..377bdeb28 100644
--- a/security/nss/lib/freebl/seed.c
+++ b/security/nss/lib/freebl/seed.c
@@ -436,8 +436,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
if (enc) {
while (len >= SEED_BLOCK_SIZE) {
- for (n = 0; n < SEED_BLOCK_SIZE; ++n)
+ for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] = in[n] ^ iv[n];
+ }
SEED_encrypt(out, out, ks);
iv = out;
@@ -447,11 +448,13 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
}
if (len) {
- for (n = 0; n < len; ++n)
+ for (n = 0; n < len; ++n) {
out[n] = in[n] ^ iv[n];
+ }
- for (n = len; n < SEED_BLOCK_SIZE; ++n)
+ for (n = len; n < SEED_BLOCK_SIZE; ++n) {
out[n] = iv[n];
+ }
SEED_encrypt(out, out, ks);
iv = out;
@@ -462,8 +465,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
while (len >= SEED_BLOCK_SIZE) {
SEED_decrypt(in, out, ks);
- for (n = 0; n < SEED_BLOCK_SIZE; ++n)
+ for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] ^= iv[n];
+ }
iv = in;
len -= SEED_BLOCK_SIZE;
@@ -474,8 +478,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
if (len) {
SEED_decrypt(in, tmp, ks);
- for (n = 0; n < len; ++n)
+ for (n = 0; n < len; ++n) {
out[n] = tmp[n] ^ iv[n];
+ }
iv = in;
}
@@ -486,8 +491,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
memcpy(tmp, in, SEED_BLOCK_SIZE);
SEED_decrypt(in, out, ks);
- for (n = 0; n < SEED_BLOCK_SIZE; ++n)
+ for (n = 0; n < SEED_BLOCK_SIZE; ++n) {
out[n] ^= ivec[n];
+ }
memcpy(ivec, tmp, SEED_BLOCK_SIZE);
len -= SEED_BLOCK_SIZE;
@@ -499,8 +505,9 @@ SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
memcpy(tmp, in, SEED_BLOCK_SIZE);
SEED_decrypt(tmp, tmp, ks);
- for (n = 0; n < len; ++n)
+ for (n = 0; n < len; ++n) {
out[n] = tmp[n] ^ ivec[n];
+ }
memcpy(ivec, tmp, SEED_BLOCK_SIZE);
}
@@ -582,6 +589,12 @@ SEED_Encrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
return SECFailure;
}
+ if ((inLen % SEED_BLOCK_SIZE) != 0 || maxOutLen < SEED_BLOCK_SIZE ||
+ maxOutLen < inLen) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
if (!cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -616,6 +629,12 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
return SECFailure;
}
+ if ((inLen % SEED_BLOCK_SIZE) != 0 || maxOutLen < SEED_BLOCK_SIZE ||
+ maxOutLen < inLen) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
if (cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
diff --git a/security/nss/lib/freebl/sha_fast.h b/security/nss/lib/freebl/sha_fast.h
index 4f37d13d0..1780ca8f4 100644
--- a/security/nss/lib/freebl/sha_fast.h
+++ b/security/nss/lib/freebl/sha_fast.h
@@ -99,6 +99,7 @@ swap4b(PRUint32 value)
defined(__ARM_ARCH_7__) || \
defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)))
+#if defined(IS_LITTLE_ENDIAN)
static __inline__ PRUint32
swap4b(PRUint32 value)
{
@@ -109,6 +110,7 @@ swap4b(PRUint32 value)
return ret;
}
#define SHA_HTONL(x) swap4b(x)
+#endif
#endif /* x86 family */
diff --git a/security/nss/lib/freebl/unix_urandom.c b/security/nss/lib/freebl/unix_urandom.c
index 869a5ed8c..720fa80bb 100644
--- a/security/nss/lib/freebl/unix_urandom.c
+++ b/security/nss/lib/freebl/unix_urandom.c
@@ -32,7 +32,7 @@ RNG_SystemRNG(void *dest, size_t maxLen)
size_t fileBytes = 0;
unsigned char *buffer = dest;
-#if defined(__OpenBSD__) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
+#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
int result;
while (fileBytes < maxLen) {
diff --git a/security/nss/lib/freebl/verified/FStar.c b/security/nss/lib/freebl/verified/FStar.c
index 4e5f6d50d..74c031876 100644
--- a/security/nss/lib/freebl/verified/FStar.c
+++ b/security/nss/lib/freebl/verified/FStar.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/FStar.h b/security/nss/lib/freebl/verified/FStar.h
index 7b105b8f2..56b1c89f8 100644
--- a/security/nss/lib/freebl/verified/FStar.h
+++ b/security/nss/lib/freebl/verified/FStar.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20.c b/security/nss/lib/freebl/verified/Hacl_Chacha20.c
index 45a743035..38f25166b 100644
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20.c
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20.h b/security/nss/lib/freebl/verified/Hacl_Chacha20.h
index f97e44b74..e7876aef7 100644
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20.h
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c
index 4eba49f47..b5568cc73 100644
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h
index 57942093d..a3970ead6 100644
--- a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h
+++ b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Curve25519.c b/security/nss/lib/freebl/verified/Hacl_Curve25519.c
index f2dcddc57..f6f6f930b 100644
--- a/security/nss/lib/freebl/verified/Hacl_Curve25519.c
+++ b/security/nss/lib/freebl/verified/Hacl_Curve25519.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Curve25519.h b/security/nss/lib/freebl/verified/Hacl_Curve25519.h
index 0e443f177..dd2615ac7 100644
--- a/security/nss/lib/freebl/verified/Hacl_Curve25519.h
+++ b/security/nss/lib/freebl/verified/Hacl_Curve25519.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c
index 246a41af3..d07a069bf 100644
--- a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h
index 4dd070026..f808bc6f9 100644
--- a/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_32.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_64.c b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.c
index 984031ae2..4d3bdde19 100644
--- a/security/nss/lib/freebl/verified/Hacl_Poly1305_64.c
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.c
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/Hacl_Poly1305_64.h b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.h
index 0aa9a0de3..e2e62193c 100644
--- a/security/nss/lib/freebl/verified/Hacl_Poly1305_64.h
+++ b/security/nss/lib/freebl/verified/Hacl_Poly1305_64.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/kremlib.h b/security/nss/lib/freebl/verified/kremlib.h
index c12164e74..69b584520 100644
--- a/security/nss/lib/freebl/verified/kremlib.h
+++ b/security/nss/lib/freebl/verified/kremlib.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/kremlib_base.h b/security/nss/lib/freebl/verified/kremlib_base.h
index 14170625d..f88f02aa5 100644
--- a/security/nss/lib/freebl/verified/kremlib_base.h
+++ b/security/nss/lib/freebl/verified/kremlib_base.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/security/nss/lib/freebl/verified/vec128.h b/security/nss/lib/freebl/verified/vec128.h
index 986e9db82..6ccecc9ec 100644
--- a/security/nss/lib/freebl/verified/vec128.h
+++ b/security/nss/lib/freebl/verified/vec128.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 INRIA and Microsoft Corporation
+/* Copyright 2016-2018 INRIA and Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.