diff options
Diffstat (limited to 'security/nss/lib/freebl')
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. |