Replace NSS with Pale Moon's

This commit is contained in:
wuggy 2026-06-29 21:29:25 +01:00
commit 8c2e376f94
2870 changed files with 1762232 additions and 1374220 deletions

View file

@ -85,11 +85,11 @@ endif
# FREEBL_PRELINK_COMMAND
#
# This is an optional environment variable which can override the default
# prelink command. It could be used on systems that did something similiar to
# prelink but used a different command and syntax. The only requirement is the
# program must take the library as the last argument, the program must output
# the original library to standard out, and the program does not need to take
# any quoted or imbedded spaces in its arguments (except the path to the
# prelink command. It could be used on systems that did something similiar to
# prelink but used a different command and syntax. The only requirement is the
# program must take the library as the last argument, the program must output
# the original library to standard out, and the program does not need to take
# any quoted or imbedded spaces in its arguments (except the path to the
# library itself, which can have imbedded spaces or special characters).
#
ifdef FREEBL_USE_PRELINK
@ -101,6 +101,9 @@ endif
ifdef NSS_NO_INIT_SUPPORT
DEFINES += -DNSS_NO_INIT_SUPPORT
endif
ifdef NSS_STRICT_INTEGRITY
DEFINES += -DNSS_STRICT_INTEGRITY_
endif
ifdef FREEBL_PRELINK_COMMAND
DEFINES +=-DFREEBL_PRELINK_COMMAND=\"$(FREEBL_PRELINK_COMMAND)\"
@ -118,36 +121,66 @@ ifneq (,$(USE_64)$(USE_X32))
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
EXTRA_SRCS += sha256-x86.c
DEFINES += -DUSE_HW_SHA2
else ifeq (1,$(CC_IS_GCC))
# Old compiler doesn't support ARM AES.
# Old compiler doesn't support Intel SHA extension
ifneq (,$(filter 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c
EXTRA_SRCS += sha256-x86.c
DEFINES += -DUSE_HW_SHA2
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES
EXTRA_SRCS += aes-armv8.c
EXTRA_SRCS += sha256-x86.c
DEFINES += -DUSE_HW_SHA2
endif
endif
endif
ifeq ($(CPU_ARCH),aarch64)
ifdef CC_IS_CLANG
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c gcm-aarch64.c sha1-armv8.c sha256-armv8.c
else ifeq (1,$(CC_IS_GCC))
# GCC versions older than 4.9 don't support ARM AES. The check
# is done in two parts, first allows "major.minor" == "4.9",
# and then rejects any major versions prior to 5. Note that
# there has been no GCC 4.10, as it was renamed to GCC 5.
ifneq (,$(filter 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c gcm-aarch64.c sha1-armv8.c sha256-armv8.c
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c gcm-aarch64.c sha1-armv8.c sha256-armv8.c
endif
endif
endif
ifeq ($(CPU_ARCH),arm)
ifndef NSS_DISABLE_ARM32_NEON
EXTRA_SRCS += gcm-arm32-neon.c
endif
ifdef CC_IS_CLANG
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c sha1-armv8.c sha256-armv8.c
else ifeq (1,$(CC_IS_GCC))
# GCC versions older than 4.9 don't support ARM AES. The check
# is done in two parts, first allows "major.minor" == "4.9",
# and then rejects any major versions prior to 5. Note that
# there has been no GCC 4.10, as it was renamed to GCC 5.
ifneq (,$(filter 4.9,$(word 1,$(GCC_VERSION)).$(word 2,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c sha1-armv8.c sha256-armv8.c
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
DEFINES += -DUSE_HW_AES -DUSE_HW_SHA1 -DUSE_HW_SHA2
EXTRA_SRCS += aes-armv8.c sha1-armv8.c sha256-armv8.c
endif
endif
endif
ifeq ($(OS_TARGET),OSF1)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
MPI_SRCS += mpvalpha.c
endif
ifeq (OS2,$(OS_TARGET))
ASFILES = mpi_x86_os2.s
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
DEFINES += -DMP_IS_LITTLE_ENDIAN
@ -168,7 +201,7 @@ ifdef NS_USE_GCC
else
# MSVC
MPI_SRCS += mpi_x86_asm.c
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
ifdef BUILD_OPT
OPTIMIZER += -Ox # maximum optimization for freebl
@ -183,6 +216,11 @@ else
INTEL_GCM_CLANG_CL = 1
endif
endif
# The Intel SHA extenstion requires Visual C++ 2015.
ifeq ($(_MSC_VER_GE_14),1)
DEFINES += -DUSE_HW_SHA2
EXTRA_SRCS += sha256-x86.c
endif
endif
else
# -DMP_NO_MP_WORD
@ -195,6 +233,7 @@ else
ifdef BUILD_OPT
OPTIMIZER += -Ox # maximum optimization for freebl
endif
ifeq ($(CPU_ARCH),x86_64)
ASFILES = arcfour-amd64-masm.asm mpi_amd64_masm.asm mp_comba_amd64_masm.asm
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DNSS_USE_COMBA
@ -208,26 +247,24 @@ else
INTEL_GCM_CLANG_CL = 1
endif
endif
# The Intel SHA extenstion requires Visual C++ 2015.
ifeq ($(_MSC_VER_GE_14),1)
DEFINES += -DUSE_HW_SHA2
EXTRA_SRCS += sha256-x86.c
endif
MPI_SRCS += mpi_amd64.c
endif
endif
endif
ifeq ($(OS_TARGET),IRIX)
ifeq ($(USE_N32),1)
ASFILES = mpi_mips.s
ifeq ($(NS_USE_GCC),1)
ASFLAGS = -Wp,-P -Wp,-traditional -O -mips3
else
ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
endif
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_USE_UINT_DIGIT
endif
endif
ifeq ($(OS_TARGET),Darwin)
ifeq ($(CPU_ARCH),x86)
ifeq ($(CPU_ARCH),x86_64)
ASFILES = mpi_amd64_common.s
DEFINES += -DMPI_AMD64 -DMP_IS_LITTLE_ENDIAN
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DNSS_USE_COMBA
MPI_SRCS += mpi_amd64.c mp_comba.c
else ifeq ($(CPU_ARCH),x86)
ASFILES = mpi_sse2.s
DEFINES += -DMP_USE_UINT_DIGIT
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
@ -237,7 +274,8 @@ endif # Darwin
ifeq ($(OS_TARGET),Linux)
ifeq ($(CPU_ARCH),x86_64)
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
# Lower case s on mpi_amd64_common due to make implicit rules.
ASFILES = arcfour-amd64-gas.s mpi_amd64_common.s
ASFLAGS += -fPIC -Wa,--noexecstack
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DNSS_USE_COMBA
@ -252,12 +290,12 @@ ifeq ($(CPU_ARCH),x86_64)
endif
ifeq ($(CPU_ARCH),x86)
ASFILES = mpi_x86.s
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT
DEFINES += -DMP_IS_LITTLE_ENDIAN
endif
ifeq ($(CPU_ARCH),arm)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_USE_UINT_DIGIT
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
MPI_SRCS += mpi_arm.c
@ -266,6 +304,15 @@ ifeq ($(CPU_ARCH),ppc)
EXTRA_SRCS += gcm-ppc.c
ifdef USE_64
DEFINES += -DNSS_NO_INIT_SUPPORT
PPC_ABI := $(shell $(CC) -dM -E - < /dev/null | awk '$$2 == "_CALL_ELF" {print $$3}')
ifeq ($(PPC_ABI),2)
ASFILES += sha512-p8.s
ifeq ($(OS_TEST),ppc64le)
DEFINES += -DPPC_GCM
EXTRA_SRCS += chacha20poly1305-ppc.c ppc-gcm-wrap.c
ASFILES += chacha20-ppc64le.s ppc-gcm.s
endif # ppc64le
endif
endif # USE_64
endif # ppc
endif # Linux
@ -282,7 +329,7 @@ ifneq ($(OS_TEST), ia64)
# PA-RISC
ASFILES += ret_cr16.s
ifndef USE_64
FREEBL_BUILD_SINGLE_SHLIB =
FREEBL_BUILD_SINGLE_SHLIB =
HAVE_ABI32_INT32 = 1
HAVE_ABI32_FPU = 1
endif
@ -293,15 +340,15 @@ ifdef USE_ABI32_INT32
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
else
ifdef USE_64
# this builds for DA2.0W (HP PA 2.0 Wide), the LP64 ABI, using 64-bit digits
MPI_SRCS += mpi_hp.c
ASFILES += hpma512.s hppa20.s
# this builds for DA2.0W (HP PA 2.0 Wide), the LP64 ABI, using 64-bit digits
MPI_SRCS += mpi_hp.c
ASFILES += hpma512.s hppa20.s
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
else
# this builds for DA2.0 (HP PA 2.0 Narrow) ABI32_FPU model
# this builds for DA2.0 (HP PA 2.0 Narrow) ABI32_FPU model
# (the 32-bit ABI with 64-bit registers) using 64-bit digits
MPI_SRCS += mpi_hp.c
ASFILES += hpma512.s hppa20.s
MPI_SRCS += mpi_hp.c
ASFILES += hpma512.s hppa20.s
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
ifndef NS_USE_GCC
ARCHFLAG = -Aa +e +DA2.0 +DS2.0
@ -336,7 +383,7 @@ else
endif # NS_USE_GCC
# Sun's WorkShop defines v8, v8plus and v9 architectures.
# gcc on Solaris defines v8 and v9 "cpus".
# gcc on Solaris defines v8 and v9 "cpus".
# gcc's v9 is equivalent to Workshop's v8plus.
# gcc's -m64 is equivalent to Workshop's v9
# We always use Sun's assembler, which uses Sun's naming convention.
@ -386,7 +433,7 @@ ifeq ($(CPU_ARCH),sparc)
FPU_TARGET_OPTIMIZER = -xchip=ultra2
endif
ifdef USE_ABI32_INT64
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# 32-bit ABI, it uses 64-bit words, integer arithmetic,
# no FPU (non-VIS cpus).
# These flags were suggested by the compiler group for building
@ -399,7 +446,7 @@ ifeq ($(CPU_ARCH),sparc)
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
endif
ifdef USE_ABI32_FPU
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# 32-bit ABI, it uses FPU code, and 32-bit word size.
# these flags were determined by running cc -### -fast and copying
# the generated flag settings
@ -441,12 +488,12 @@ ifeq ($(CPU_ARCH),sparc)
### set flags for both GCC and Sun cc
ifdef USE_ABI32_INT64
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# 32-bit ABI, it uses 64-bit words, integer arithmetic, no FPU
# best times are with no MP_ flags specified
endif
ifdef USE_ABI32_FPU
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers,
# 32-bit ABI, it uses FPU code, and 32-bit word size
MPI_SRCS += mpi_sparc.c
ASFILES = mpv_sparcv8.s montmulfv8.s
@ -476,7 +523,7 @@ else
ifeq ($(USE_64),1)
# Solaris for AMD64
ifdef NS_USE_GCC
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
ASFILES = arcfour-amd64-gas.s mpi_amd64_common.s
ASFLAGS += -march=opteron -m64 -fPIC
MPI_SRCS += mp_comba.c
# comment the next four lines to turn off Intel HW acceleration
@ -502,7 +549,7 @@ else
else
# Solaris x86
DEFINES += -DMP_USE_UINT_DIGIT
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
ASFILES = mpi_i86pc.s
ifndef NS_USE_GCC
@ -525,51 +572,50 @@ ifneq ($(shell $(CC) -? 2>&1 >/dev/null </dev/null | sed -e 's/:.*//;1q'),lcc)
HAVE_INT128_SUPPORT = 1
DEFINES += -DHAVE_INT128_SUPPORT
endif
ifneq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
NSS_DISABLE_AVX2 = 1
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
HAVE_INT128_SUPPORT = 1
DEFINES += -DHAVE_INT128_SUPPORT
endif
ifeq (,$(filter 0 1 2 3 4,$(word 1,$(GCC_VERSION))))
NSS_DISABLE_SSE3 = 1
NSS_DISABLE_SSE4_1 = 1
NSS_DISABLE_SSE4_2 = 1
endif
endif
endif # lcc
endif # USE_64
ifndef HAVE_INT128_SUPPORT
DEFINES += -DKRML_NOUINT128
DEFINES += -DKRML_VERIFIED_UINT128
endif
ifndef NSS_DISABLE_CHACHAPOLY
ifeq ($(CPU_ARCH),x86_64)
ifdef HAVE_INT128_SUPPORT
EXTRA_SRCS += Hacl_Poly1305_64.c
else
EXTRA_SRCS += Hacl_Poly1305_32.c
endif
else
ifeq ($(CPU_ARCH),aarch64)
EXTRA_SRCS += Hacl_Poly1305_64.c
else
EXTRA_SRCS += Hacl_Poly1305_32.c
ifndef NSS_DISABLE_AVX2
EXTRA_SRCS += Hacl_Poly1305_256.c Hacl_Chacha20_Vec256.c Hacl_Chacha20Poly1305_256.c
DEFINES += -DHACL_CAN_COMPILE_VEC256
endif # NSS_DISABLE_AVX2
ifndef NSS_DISABLE_SSE3
EXTRA_SRCS += Hacl_Poly1305_128.c Hacl_Chacha20_Vec128.c Hacl_Chacha20Poly1305_128.c
DEFINES += -DHACL_CAN_COMPILE_VEC128
endif
endif # x86_64
VERIFIED_SRCS += Hacl_Chacha20.c
VERIFIED_SRCS += Hacl_Chacha20_Vec128.c
VERIFIED_SRCS += Hacl_Poly1305_32.c Hacl_Chacha20.c Hacl_Chacha20Poly1305_32.c
endif # NSS_DISABLE_CHACHAPOLY
ifeq (,$(filter-out i386 x386 x86 x86_64 aarch64,$(CPU_ARCH)))
# All intel architectures get the 64 bit version
# With custom uint128 if necessary (faster than generic 32 bit version).
ifeq (,$(filter-out x86_64 aarch64,$(CPU_ARCH)))
# All 64-bit architectures get the 64 bit version.
ECL_SRCS += curve25519_64.c
VERIFIED_SRCS += Hacl_Curve25519.c
VERIFIED_SRCS += Hacl_Curve25519_51.c
else
# All non intel architectures get the generic 32 bit implementation (slow!)
# All other architectures get the generic 32 bit implementation
ECL_SRCS += curve25519_32.c
endif
ifndef HAVE_INT128_SUPPORT
VERIFIED_SRCS += FStar.c
endif
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
@ -586,24 +632,23 @@ include $(CORE_DEPTH)/coreconf/rules.mk
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
rijndael_tables:
$(CC) -o $(OBJDIR)/make_rijndael_tab rijndael_tables.c \
$(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a
$(OBJDIR)/make_rijndael_tab
vpath %.h mpi ecl verified
vpath %.c mpi ecl verified
vpath %.h mpi ecl verified deprecated
vpath %.c mpi ecl verified deprecated
vpath %.S mpi ecl
vpath %.s mpi ecl
vpath %.asm mpi ecl
INCLUDES += -Impi -Iecl -Iverified
INCLUDES += -Impi -Iecl -Iverified -Iverified/internal -Iverified/karamel/include -Iverified/karamel/krmllib/dist/minimal -Ideprecated
DEFINES += -DMP_API_COMPATIBLE
MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c
MPI_USERS = secmpi.c dh.c pqg.c dsa.c rsa.c ec.c
MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX)))
MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX)))
@ -625,12 +670,10 @@ $(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h
ifeq ($(SYSV_SPARC),1)
$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/mpv_sparcv8x.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s
@$(MAKE_OBJDIR)
$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/mpv_sparcv8x.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s | $$(@D)/d
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s
@$(MAKE_OBJDIR)
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s | $$(@D)/d
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
$(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h
@ -641,103 +684,35 @@ ifndef FREEBL_CHILD_BUILD
# Parent build. This is where we decide which shared libraries to build
ifdef FREEBL_BUILD_SINGLE_SHLIB
# too suppress the SINGLE_SHLIB override warning
FREEBL_OBJDIRS :=
################### Single shared lib stuff #########################
SINGLE_SHLIB_DIR = $(OBJDIR)/$(OS_TARGET)_SINGLE_SHLIB
ALL_TRASH += $(SINGLE_SHLIB_DIR)
$(SINGLE_SHLIB_DIR):
-mkdir -p $(SINGLE_SHLIB_DIR)
release_md libs:: $(SINGLE_SHLIB_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 \
OBJDIR=$(SINGLE_SHLIB_DIR) $@
######################## common stuff #########################
define target_freebl_SHLIB
ifdef $(2)
$(1)_DIR = $$(OBJDIR)/$$(OS_TARGET)_$(1)
ALL_TRASH += $$($(1)_DIR)
ifeq (,$$(filter $$($(1)_DIR)/d,$$(FREEBL_OBJDIRS)))
FREEBL_OBJDIRS += $$($(1)_DIR)/d
endif
ifdef NEED_STUB_BUILD
SINGLE_SHLIB_DIR = $(OBJDIR)/$(OS_TARGET)_SINGLE_SHLIB
ALL_TRASH += $(SINGLE_SHLIB_DIR)
$(SINGLE_SHLIB_DIR):
-mkdir $(SINGLE_SHLIB_DIR)
release_md libs:: $(SINGLE_SHLIB_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_STUB_BUILD=1 \
OBJDIR=$(SINGLE_SHLIB_DIR) $@
release_md:: freebl_$(2)
libs: freebl_$(2)
freebl_$(2): | $$($(1)_DIR)/d
$$(MAKE) FREEBL_CHILD_BUILD=1 $(3)=1 OBJDIR=$$($(1)_DIR) libs
endif
endef # target_freebl_SHLIB
# multiple shared libraries
target_freebl_ABI = $(call target_freebl_SHLIB,$(1),HAVE_$(1),USE_$(1))
######################## ABI32_FPU stuff #########################
ifdef HAVE_ABI32_FPU
ABI32_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_FPU
ALL_TRASH += $(ABI32_FPU_DIR)
$(eval $(call target_freebl_SHLIB,SINGLE_SHLIB,FREEBL_BUILD_SINGLE_SHLIB,NEEDED_DUMMY))
$(eval $(call target_freebl_SHLIB,SINGLE_SHLIB,NEED_STUB_BUILD,USE_STUB_BUILD))
$(ABI32_FPU_DIR):
-mkdir $(ABI32_FPU_DIR)
release_md libs:: $(ABI32_FPU_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_FPU=1 \
OBJDIR=$(ABI32_FPU_DIR) $@
endif
######################## ABI32_INT32 stuff #########################
ifdef HAVE_ABI32_INT32
ABI32_INT32_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT32
ALL_TRASH += $(ABI32_INT32_DIR)
$(ABI32_INT32_DIR):
-mkdir $(ABI32_INT32_DIR)
release_md libs:: $(ABI32_INT32_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT32=1 \
OBJDIR=$(ABI32_INT32_DIR) $@
endif
######################## ABI32_INT64 stuff #########################
ifdef HAVE_ABI32_INT64
ABI32_INT64_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT64
ALL_TRASH += $(ABI32_INT64_DIR)
$(ABI32_INT64_DIR):
-mkdir $(ABI32_INT64_DIR)
release_md libs:: $(ABI32_INT64_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT64=1\
OBJDIR=$(ABI32_INT64_DIR) $@
endif
######################## END of 32-bit stuff #########################
# above is 32-bit builds, below is 64-bit builds
######################## ABI64_FPU stuff #########################
ifdef HAVE_ABI64_FPU
ABI64_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_FPU
ALL_TRASH += $(ABI64_FPU_DIR)
$(ABI64_FPU_DIR):
-mkdir $(ABI64_FPU_DIR)
release_md libs:: $(ABI64_FPU_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_FPU=1 \
OBJDIR=$(ABI64_FPU_DIR) $@
endif
######################## ABI64_INT stuff #########################
ifdef HAVE_ABI64_INT
ABI64_INT_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_INT
ALL_TRASH += $(ABI64_INT_DIR)
$(ABI64_INT_DIR):
-mkdir $(ABI64_INT_DIR)
release_md libs:: $(ABI64_INT_DIR)
$(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_INT=1 \
OBJDIR=$(ABI64_INT_DIR) $@
endif
$(eval $(call target_freebl_ABI,ABI32_FPU))
$(eval $(call target_freebl_ABI,ABI32_INT32))
$(eval $(call target_freebl_ABI,ABI32_INT64))
$(eval $(call target_freebl_ABI,ABI64_FPU))
$(eval $(call target_freebl_ABI,ABI64_INT))
endif # FREEBL_CHILD_BUILD
@ -746,8 +721,7 @@ endif # FREEBL_CHILD_BUILD
# ANSI C's strict aliasing rules.
ifeq ($(OS_TARGET),Linux)
ifneq ($(CPU_ARCH),x86)
$(OBJDIR)/$(PROG_PREFIX)desblapi$(OBJ_SUFFIX): desblapi.c
@$(MAKE_OBJDIR)
$(OBJDIR)/$(PROG_PREFIX)desblapi$(OBJ_SUFFIX): desblapi.c | $$(@D)/d
ifdef NEED_ABSOLUTE_PATH
$(CC) -o $@ -c $(CFLAGS) -fno-strict-aliasing $(call core_abspath,$<)
else
@ -779,14 +753,52 @@ ifdef INTEL_GCM_CLANG_CL
$(OBJDIR)/$(PROG_PREFIX)intel-gcm-wrap$(OBJ_SUFFIX): CFLAGS += -mssse3
endif
$(OBJDIR)/$(PROG_PREFIX)sha256-x86$(OBJ_SUFFIX): CFLAGS += -msha -mssse3 -msse4.1
ifeq ($(CPU_ARCH),arm)
$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8
# When the compiler uses the softfloat ABI, we want to use the compatible softfp ABI when
# enabling NEON for these objects.
# Confusingly, __SOFTFP__ is the name of the define for the softfloat ABI, not for the softfp ABI.
USES_SOFTFLOAT_ABI := $(shell $(CC) -o - -E -dM - $(CFLAGS) < /dev/null | grep __SOFTFP__ > /dev/null && echo 1)
$(OBJDIR)/$(PROG_PREFIX)aes-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8$(if $(USES_SOFTFLOAT_ABI), -mfloat-abi=softfp)
$(OBJDIR)/$(PROG_PREFIX)sha1-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8$(if $(USES_SOFTFLOAT_ABI), -mfloat-abi=softfp)
$(OBJDIR)/$(PROG_PREFIX)sha256-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a -mfpu=crypto-neon-fp-armv8$(if $(USES_SOFTFLOAT_ABI), -mfloat-abi=softfp)
ifndef NSS_DISABLE_ARM32_NEON
$(OBJDIR)/$(PROG_PREFIX)gcm-arm32-neon$(OBJ_SUFFIX): CFLAGS += -mfpu=neon$(if $(USES_SOFTFLOAT_ABI), -mfloat-abi=softfp)
endif
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
$(OBJDIR)/$(PROG_PREFIX)sha1-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
$(OBJDIR)/$(PROG_PREFIX)sha256-armv8$(OBJ_SUFFIX): CFLAGS += -march=armv8-a+crypto
endif
ifeq ($(CPU_ARCH),ppc)
$(OBJDIR)/$(PROG_PREFIX)gcm-ppc$(OBJ_SUFFIX): CFLAGS += -mcrypto -maltivec
$(OBJDIR)/$(PROG_PREFIX)sha512$(OBJ_SUFFIX): CFLAGS += -funroll-loops -fpeel-loops
ifneq ($(NSS_DISABLE_ALTIVEC),1)
$(OBJDIR)/$(PROG_PREFIX)gcm-ppc$(OBJ_SUFFIX): CFLAGS += -maltivec
$(OBJDIR)/$(PROG_PREFIX)gcm$(OBJ_SUFFIX): CFLAGS += -maltivec
$(OBJDIR)/$(PROG_PREFIX)rijndael$(OBJ_SUFFIX): CFLAGS += -maltivec
$(OBJDIR)/$(PROG_PREFIX)sha512$(OBJ_SUFFIX): CFLAGS += -maltivec
$(OBJDIR)/$(PROG_PREFIX)chacha20poly1305-ppc$(OBJ_SUFFIX): CFLAGS += -maltivec
endif
ifneq ($(NSS_DISABLE_CRYPTO_VSX),1)
$(OBJDIR)/$(PROG_PREFIX)gcm-ppc$(OBJ_SUFFIX): CFLAGS += -mcrypto -mvsx
$(OBJDIR)/$(PROG_PREFIX)gcm$(OBJ_SUFFIX): CFLAGS += -mcrypto -mvsx
$(OBJDIR)/$(PROG_PREFIX)rijndael$(OBJ_SUFFIX): CFLAGS += -mcrypto -mvsx
$(OBJDIR)/$(PROG_PREFIX)sha512$(OBJ_SUFFIX): CFLAGS += -mcrypto -mvsx
$(OBJDIR)/$(PROG_PREFIX)chacha20poly1305-ppc$(OBJ_SUFFIX): CFLAGS += -mcrypto -mvsx
endif
endif
$(OBJDIR)/$(PROG_PREFIX)Hacl_Chacha20_Vec128$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx
$(OBJDIR)/$(PROG_PREFIX)Hacl_Chacha20Poly1305_128$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx
$(OBJDIR)/$(PROG_PREFIX)Hacl_Poly1305_128$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx
ifndef NSS_DISABLE_AVX2
$(OBJDIR)/$(PROG_PREFIX)Hacl_Chacha20Poly1305_256$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx2
$(OBJDIR)/$(PROG_PREFIX)Hacl_Chacha20_Vec256$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx -mavx2
$(OBJDIR)/$(PROG_PREFIX)Hacl_Poly1305_256$(OBJ_SUFFIX): CFLAGS += -mssse3 -msse4.1 -msse4.2 -mavx -mavx2
endif

View file

@ -8,7 +8,7 @@
#if ((defined(__clang__) || \
(defined(__GNUC__) && defined(__GNUC_MINOR__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)))) && \
(defined(__ARM_NEON) || defined(__ARM_NEON__)))
defined(IS_LITTLE_ENDIAN))
#ifndef __ARM_FEATURE_CRYPTO
#error "Compiler option is invalid"

View file

@ -67,7 +67,7 @@ native_key_expansion192(AESContext *cx, const unsigned char *key)
pre_align __m128i tmp3 post_align;
pre_align __m128i carry post_align;
keySchedule[0] = _mm_loadu_si128((__m128i *)key);
keySchedule[1] = _mm_loadu_si128((__m128i *)(key + 16));
keySchedule[1] = _mm_loadl_epi64((__m128i *)(key + 16));
EXPAND_KEY192(keySchedule[0], keySchedule[1], keySchedule[2],
keySchedule[3], carry, 0x1, 0x2);
EXPAND_KEY192_PART2(keySchedule[4], carry, keySchedule[3]);
@ -146,7 +146,7 @@ rijndael_native_encryptBlock(AESContext *cx,
unsigned char *output,
const unsigned char *input)
{
int i;
unsigned int i;
pre_align __m128i m post_align = _mm_loadu_si128((__m128i *)input);
m = _mm_xor_si128(m, cx->k.keySchedule[0]);
for (i = 1; i < cx->Nr; ++i) {

View file

@ -9,6 +9,8 @@
#include "stubs.h"
#endif
#include <stddef.h>
#include "prcpucfg.h"
#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
@ -196,11 +198,33 @@ set_t(unsigned char *pt, unsigned long t)
#endif
static void
encode_PRUint32_BE(unsigned char *data, PRUint32 val)
{
size_t i;
for (i = 0; i < sizeof(PRUint32); i++) {
data[i] = PORT_GET_BYTE_BE(val, i, sizeof(PRUint32));
}
}
static PRUint32
decode_PRUint32_BE(unsigned char *data)
{
PRUint32 val = 0;
size_t i;
for (i = 0; i < sizeof(PRUint32); i++) {
val = (val << PR_BITS_PER_BYTE) | data[i];
}
return val;
}
/*
** Perform AES key wrap.
** Perform AES key wrap W function.
** "cx" the context
** "iv" the iv is concatenated to the plain text for for executing the function
** "output" the output buffer to store the encrypted data.
** "outputLen" how much data is stored in "output". Set by the routine
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
@ -208,9 +232,9 @@ set_t(unsigned char *pt, unsigned long t)
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
AESKeyWrap_W(AESKeyWrapContext *cx, unsigned char *iv, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
PRUint64 *R = NULL;
unsigned int nBlocks;
@ -251,7 +275,7 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
/*
** 1) Initialize variables.
*/
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
memcpy(&A, iv, AES_KEY_WRAP_IV_BYTES);
memcpy(&R[1], input, inputLen);
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
t = 0;
@ -294,10 +318,12 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
#undef A
/*
** Perform AES key unwrap.
** Perform AES key wrap W^-1 function.
** "cx" the context
** "iv" the input IV to verify against. If NULL, then skip verification.
** "ivOut" the output buffer to store the IV (optional).
** "output" the output buffer to store the decrypted data.
** "outputLen" how much data is stored in "output". Set by the routine
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
@ -305,9 +331,10 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
AESKeyWrap_Winv(AESKeyWrapContext *cx, unsigned char *iv,
unsigned char *ivOut, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
PRUint64 *R = NULL;
unsigned int nBlocks;
@ -378,11 +405,14 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
** 3) Output the results.
*/
if (s == SECSuccess) {
int bad = memcmp(&B[0], cx->iv, AES_KEY_WRAP_IV_BYTES);
int bad = (iv) && memcmp(&B[0], iv, AES_KEY_WRAP_IV_BYTES);
if (!bad) {
memcpy(output, &R[1], outLen);
if (pOutputLen)
*pOutputLen = outLen;
if (ivOut) {
memcpy(ivOut, &B[0], AES_KEY_WRAP_IV_BYTES);
}
} else {
s = SECFailure;
PORT_SetError(SEC_ERROR_BAD_DATA);
@ -396,3 +426,217 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
return s;
}
#undef A
/*
** Perform AES key wrap.
** "cx" the context
** "output" the output buffer to store the encrypted data.
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
return AESKeyWrap_W(cx, cx->iv, output, pOutputLen, maxOutputLen,
input, inputLen);
}
/*
** Perform AES key unwrap.
** "cx" the context
** "output" the output buffer to store the decrypted data.
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
return AESKeyWrap_Winv(cx, cx->iv, NULL, output, pOutputLen, maxOutputLen,
input, inputLen);
}
#define BLOCK_PAD_POWER2(x, bs) (((bs) - ((x) & ((bs)-1))) & ((bs)-1))
#define AES_KEY_WRAP_ICV2 0xa6, 0x59, 0x59, 0xa6
#define AES_KEY_WRAP_ICV2_INT32 0xa65959a6
#define AES_KEY_WRAP_ICV2_LEN 4
/*
** Perform AES key wrap with padding.
** "cx" the context
** "output" the output buffer to store the encrypted data.
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
unsigned int padLen = BLOCK_PAD_POWER2(inputLen, AES_KEY_WRAP_BLOCK_SIZE);
unsigned int paddedInputLen = inputLen + padLen;
unsigned int outLen = paddedInputLen + AES_KEY_WRAP_BLOCK_SIZE;
unsigned char iv[AES_BLOCK_SIZE] = { AES_KEY_WRAP_ICV2 };
unsigned char *newBuf;
SECStatus rv;
*pOutputLen = outLen;
if (maxOutputLen < outLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
PORT_Assert((AES_KEY_WRAP_ICV2_LEN + sizeof(PRUint32)) == AES_KEY_WRAP_BLOCK_SIZE);
encode_PRUint32_BE(iv + AES_KEY_WRAP_ICV2_LEN, inputLen);
/* If we can fit in an AES Block, just do and AES Encrypt,
* iv is big enough to handle this on the stack, so no need to allocate
*/
if (outLen == AES_BLOCK_SIZE) {
PORT_Assert(inputLen <= AES_KEY_WRAP_BLOCK_SIZE);
PORT_Memset(iv + AES_KEY_WRAP_BLOCK_SIZE, 0, AES_KEY_WRAP_BLOCK_SIZE);
PORT_Memcpy(iv + AES_KEY_WRAP_BLOCK_SIZE, input, inputLen);
rv = AES_Encrypt(&cx->aescx, output, pOutputLen, maxOutputLen, iv,
outLen);
PORT_Memset(iv, 0, sizeof(iv));
return rv;
}
/* add padding to our input block */
newBuf = PORT_ZAlloc(paddedInputLen);
if (newBuf == NULL) {
return SECFailure;
}
PORT_Memcpy(newBuf, input, inputLen);
rv = AESKeyWrap_W(cx, iv, output, pOutputLen, maxOutputLen,
newBuf, paddedInputLen);
PORT_ZFree(newBuf, paddedInputLen);
/* a little overkill, we only need to clear out the length, but this
* is easier to verify we got it all */
PORT_Memset(iv, 0, sizeof(iv));
return rv;
}
/*
** Perform AES key unwrap with padding.
** "cx" the context
** "output" the output buffer to store the decrypted data.
** "pOutputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_DecryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *pOutputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
unsigned int padLen;
unsigned int padLen2;
unsigned int outLen;
unsigned int paddedLen;
unsigned int good;
unsigned char *newBuf = NULL;
unsigned char *allocBuf = NULL;
int i;
unsigned char iv[AES_BLOCK_SIZE];
PRUint32 magic;
SECStatus rv = SECFailure;
paddedLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
/* unwrap the padded result */
if (inputLen == AES_BLOCK_SIZE) {
rv = AES_Decrypt(&cx->aescx, iv, &outLen, inputLen, input, inputLen);
newBuf = &iv[AES_KEY_WRAP_BLOCK_SIZE];
outLen -= AES_KEY_WRAP_BLOCK_SIZE;
} else {
/* if the caller supplied enough space to hold the unpadded buffer,
* we can unwrap directly into that unpadded buffer. Otherwise
* we allocate a buffer that can hold the padding, and we'll copy
* the result in a later step */
newBuf = output;
if (maxOutputLen < paddedLen) {
allocBuf = newBuf = PORT_Alloc(paddedLen);
if (!allocBuf) {
return SECFailure;
}
}
/* We pass NULL for the first IV argument because we don't know
* what the IV has since in includes the length, so we don't have
* Winv verify it. We pass iv in the second argument to get the
* iv, which we verify below before we return anything */
rv = AESKeyWrap_Winv(cx, NULL, iv, newBuf, &outLen,
paddedLen, input, inputLen);
}
if (rv != SECSuccess) {
goto loser;
}
rv = SECFailure;
if (outLen != paddedLen) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
goto loser;
}
/* we verify the result in a constant time manner */
/* verify ICV magic */
magic = decode_PRUint32_BE(iv);
good = PORT_CT_EQ(magic, AES_KEY_WRAP_ICV2_INT32);
/* fetch and verify plain text length */
outLen = decode_PRUint32_BE(iv + AES_KEY_WRAP_ICV2_LEN);
good &= PORT_CT_LE(outLen, paddedLen);
/* now verify the padding */
padLen = paddedLen - outLen;
padLen2 = BLOCK_PAD_POWER2(outLen, AES_KEY_WRAP_BLOCK_SIZE);
good &= PORT_CT_EQ(padLen, padLen2);
for (i = 0; i < AES_KEY_WRAP_BLOCK_SIZE; i++) {
unsigned int doTest = PORT_CT_GT(padLen, i);
unsigned int result = PORT_CT_ZERO(newBuf[paddedLen - i - 1]);
good &= PORT_CT_SEL(doTest, result, PORT_CT_TRUE);
}
/* now if anything was wrong, fail. At this point we will leak timing
* information, but we also 'leak' the error code as well. */
if (!good) {
PORT_SetError(SEC_ERROR_BAD_DATA);
goto loser;
}
/* now copy out the result */
*pOutputLen = outLen;
if (maxOutputLen < outLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
goto loser;
}
if (output != newBuf) {
PORT_Memcpy(output, newBuf, outLen);
}
rv = SECSuccess;
loser:
/* if we failed, make sure we don't return any data to the user */
if ((rv != SECSuccess) && (output == newBuf)) {
PORT_Memset(newBuf, 0, paddedLen);
}
/* clear out CSP sensitive data from the heap and stack */
if (allocBuf) {
PORT_ZFree(allocBuf, paddedLen);
}
PORT_Memset(iv, 0, sizeof(iv));
return rv;
}

View file

@ -37,27 +37,18 @@ HMAC_Destroy(HMACContext *cx, PRBool freeit)
PORT_Free(cx);
}
SECStatus
HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
static SECStatus
hmac_initKey(HMACContext *cx, const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS)
{
unsigned int i;
unsigned char hashed_secret[HASH_LENGTH_MAX];
/* required by FIPS 198 Section 3 */
if (isFIPS && secret_len < hash_obj->length / 2) {
if (isFIPS && secret_len < cx->hashobj->length / 2) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
cx->wasAllocated = PR_FALSE;
cx->hashobj = hash_obj;
cx->hash = cx->hashobj->create();
if (cx->hash == NULL)
goto loser;
if (secret_len > cx->hashobj->blocklength) {
cx->hashobj->begin(cx->hash);
@ -85,6 +76,31 @@ HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
loser:
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
return SECFailure;
}
SECStatus
HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
{
SECStatus rv;
if (cx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
cx->wasAllocated = PR_FALSE;
cx->hashobj = hash_obj;
cx->hash = cx->hashobj->create();
if (cx->hash == NULL)
goto loser;
rv = hmac_initKey(cx, secret, secret_len, isFIPS);
if (rv != SECSuccess)
goto loser;
return rv;
loser:
if (cx->hash != NULL)
cx->hashobj->destroy(cx->hash, PR_TRUE);
return SECFailure;
@ -107,6 +123,34 @@ HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
return cx;
}
/* this allows us to reuse an existing HMACContext with a new key and
* Hash function */
SECStatus
HMAC_ReInit(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
{
PRBool wasAllocated;
SECStatus rv;
/* if we are using the same hash, keep the hash contexts and only
* init the key */
if ((cx->hashobj == hash_obj) && (cx->hash != NULL)) {
return hmac_initKey(cx, secret, secret_len, isFIPS);
}
/* otherwise we destroy the contents of the context and
* initalize it from scratch. We need to preseve the current state
* of wasAllocated to the final destroy works correctly */
wasAllocated = cx->wasAllocated;
cx->wasAllocated = PR_FALSE;
HMAC_Destroy(cx, PR_FALSE);
rv = HMAC_Init(cx, hash_obj, secret, secret_len, isFIPS);
if (rv != SECSuccess) {
return rv;
}
cx->wasAllocated = wasAllocated;
return SECSuccess;
}
void
HMAC_Begin(HMACContext *cx)
{

View file

@ -30,6 +30,12 @@ SECStatus
HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS);
/* like HMAC_Init, except caller passes in an existing context
* previously used by either HMAC_Create or HMAC_Init. */
SECStatus
HMAC_ReInit(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS);
/* reset HMAC for a fresh round */
extern void
HMAC_Begin(HMACContext *cx);

View file

@ -16,8 +16,10 @@ typedef __vector unsigned short vec_u16;
typedef __vector signed short vec_s16;
typedef __vector unsigned int vec_u32;
typedef __vector signed int vec_s32;
#ifdef __VSX__
typedef __vector unsigned long long vec_u64;
typedef __vector signed long long vec_s64;
#endif
typedef __vector float vec_f;
#endif

View file

@ -22,7 +22,7 @@
#define CONVERT_TO_WORDS
#endif
#if defined(AIX) || defined(OSF1) || defined(NSS_BEVAND_ARCFOUR)
#if defined(AIX) || defined(NSS_BEVAND_ARCFOUR)
/* Treat array variables as words, not bytes, on CPUs that take
* much longer to write bytes than to write words, or when using
* assembler code that required it.

View file

@ -380,6 +380,9 @@ extern SECStatus KEA_Derive(SECItem *prime,
*/
extern PRBool KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime);
/* verify a value is prime */
PRBool KEA_PrimeCheck(SECItem *prime);
/****************************************
* J-PAKE key transport
*/
@ -856,6 +859,28 @@ extern SECStatus
AES_Decrypt(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
/*
** Perform AES AEAD operation (either encrypt or decrypt), controlled by
** the context.
** "cx" the context
** "output" the output buffer to store the encrypted data.
** "outputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
** "params" pointer to an AEAD specific param PKCS #11 param structure
** "paramsLen" length of the param structure pointed to by params
** "aad" addition authenticated data
** "aadLen" the amount of additional authenticated data.
*/
extern SECStatus
AES_AEAD(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
void *params, unsigned int paramsLen,
const unsigned char *aad, unsigned int aadLen);
/******************************************/
/*
@ -922,6 +947,38 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
/*
** Perform AES padded key wrap.
** "cx" the context
** "output" the output buffer to store the encrypted data.
** "outputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
/*
** Perform AES padded key unwrap.
** "cx" the context
** "output" the output buffer to store the decrypted data.
** "outputLen" how much data is stored in "output". Set by the routine
** after some data is stored in output.
** "maxOutputLen" the maximum amount of data that can ever be
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus
AESKeyWrap_DecryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
/******************************************/
/*
** Camellia symmetric block cypher
@ -984,6 +1041,26 @@ Camellia_Decrypt(CamelliaContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
/******************************************/
/*
** ChaCha20 block cipher
*/
extern SECStatus ChaCha20_InitContext(ChaCha20Context *ctx,
const unsigned char *key,
unsigned int keyLen,
const unsigned char *nonce,
unsigned int nonceLen,
PRUint32 ctr);
extern ChaCha20Context *ChaCha20_CreateContext(const unsigned char *key,
unsigned int keyLen,
const unsigned char *nonce,
unsigned int nonceLen,
PRUint32 ctr);
extern void ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit);
/******************************************/
/*
** ChaCha20+Poly1305 AEAD
@ -1014,6 +1091,20 @@ extern SECStatus ChaCha20Poly1305_Open(
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen);
extern SECStatus ChaCha20Poly1305_Encrypt(
const ChaCha20Poly1305Context *ctx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen, unsigned char *tagOut);
extern SECStatus ChaCha20Poly1305_Decrypt(
const ChaCha20Poly1305Context *ctx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen, unsigned char *tagIn);
extern SECStatus ChaCha20_Xor(
unsigned char *output, const unsigned char *block, unsigned int len,
const unsigned char *k, const unsigned char *nonce, PRUint32 ctr);
@ -1430,7 +1521,7 @@ extern SECStatus BLAKE2B_MAC_HashBuf(unsigned char *output,
/*
** Create a new Blake2b context
*/
extern BLAKE2BContext *BLAKE2B_NewContext();
extern BLAKE2BContext *BLAKE2B_NewContext(void);
/*
** Destroy a Blake2b secure hash context.

View file

@ -18,12 +18,18 @@ typedef SECStatus (*freeblCipherFunc)(void *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
unsigned int blocksize);
typedef SECStatus (*freeblAeadFunc)(void *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
void *params, unsigned int paramsLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
typedef void (*freeblDestroyFunc)(void *cx, PRBool freeit);
SEC_BEGIN_PROTOS
#ifndef NSS_FIPS_DISABLED
SECStatus BL_FIPSEntryOK(PRBool freeblOnly);
SECStatus BL_FIPSEntryOK(PRBool freeblOnly, PRBool rerun);
PRBool BL_POSTRan(PRBool freeblOnly);
#endif
@ -54,10 +60,10 @@ SEC_END_PROTOS
#endif
/* Alignment helpers. */
#if defined(_WINDOWS) && defined(NSS_X86_OR_X64)
#if defined(_MSC_VER)
#define pre_align __declspec(align(16))
#define post_align
#elif defined(NSS_X86_OR_X64)
#elif defined(__GNUC__)
#define pre_align
#define post_align __attribute__((aligned(16)))
#else
@ -79,8 +85,12 @@ SECStatus generate_prime(mp_int *prime, int primeLen);
/* Freebl state. */
PRBool aesni_support();
PRBool clmul_support();
PRBool sha_support();
PRBool avx_support();
PRBool avx2_support();
PRBool ssse3_support();
PRBool sse4_1_support();
PRBool sse4_2_support();
PRBool arm_neon_support();
PRBool arm_aes_support();
PRBool arm_pmull_support();
@ -88,4 +98,14 @@ PRBool arm_sha1_support();
PRBool arm_sha2_support();
PRBool ppc_crypto_support();
#ifdef NSS_FIPS_DISABLED
#define BLAPI_CLEAR_STACK(stack_size)
#else
#define BLAPI_CLEAR_STACK(stack_size) \
{ \
volatile char _stkclr[stack_size]; \
PORT_Memset((void *)&_stkclr[0], 0, stack_size); \
}
#endif
#endif /* _BLAPII_H_ */

View file

@ -114,9 +114,9 @@ typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
#define BLAKE2B_BLOCK_LENGTH 128 /* Bytes */
#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH
#define AES_KEY_WRAP_IV_BYTES 8
#define AES_KEY_WRAP_BLOCK_SIZE 8 /* bytes */
#define AES_BLOCK_SIZE 16 /* bytes */
#define AES_BLOCK_SIZE 16 /* bytes */
#define AES_KEY_WRAP_BLOCK_SIZE (AES_BLOCK_SIZE / 2)
#define AES_KEY_WRAP_IV_BYTES AES_KEY_WRAP_BLOCK_SIZE
#define AES_128_KEY_LENGTH 16 /* bytes */
#define AES_192_KEY_LENGTH 24 /* bytes */
@ -199,6 +199,39 @@ typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
*/
#define PQG_INDEX_TO_PBITS(j) (((unsigned)(j) > 8) ? -1 : (512 + 64 * (j)))
/* When we are generating a gcm iv from a random number, we need to calculate
* an acceptable iteration count to avoid birthday attacks. (randomly
* generating the same IV twice).
*
* We use the approximation n = sqrt(2*m*p) to find an acceptable n given m
* and p.
* where n is the number of iterations.
* m is the number of possible random values.
* p is the probability of collision (0-1).
*
* We want to calculate the constant number GCM_IV_RANDOM_BIRTHDAY_BITS, which
* is the number of bits we subtract off of the length of the iv (in bits) to
* get a safe count value (log2).
*
* Since we do the calculation in bits, so we need to take the whole
* equation log2:
* log2 n = (1+(log2 m)+(log2 p))/2
* Since p < 1, log2 p is negative. Also note that the length of the iv in
* bits is log2 m, so if we set GCMIV_RANDOM_BIRTHDAY_BITS =- log2 p - 1.
* then we can calculate a safe counter value with:
* n = 2^((ivLenBits - GCMIV_RANDOM_BIRTHDAY_BITS)/2)
*
* If we arbitrarily set p = 10^-18 (1 chance in trillion trillion operation)
* we get GCMIV_RANDOM_BIRTHDAY_BITS = -(-18)/.301 -1 = 59 (.301 = log10 2)
* GCMIV_RANDOM_BIRTHDAY_BITS should be at least 59, call it a round 64. NOTE:
* the variable IV size for TLS is 64 bits, which explains why it's not safe
* to use a random value for the nonce in TLS. */
#define GCMIV_RANDOM_BIRTHDAY_BITS 64
/* flag to tell BLAPI_Verify* to rerun the post and integrity tests */
#define BLAPI_FIPS_RERUN_FLAG '\377' /* 0xff, 255 invalide code for UFT8/ASCII */
#define BLAPI_FIPS_RERUN_FLAG_STRING "\377" /* The above as a C string */
/***************************************************************************
** Opaque objects
*/
@ -216,6 +249,7 @@ struct SHA256ContextStr;
struct SHA512ContextStr;
struct AESKeyWrapContextStr;
struct SEEDContextStr;
struct ChaCha20ContextStr;
struct ChaCha20Poly1305ContextStr;
struct Blake2bContextStr;
@ -236,6 +270,7 @@ typedef struct SHA512ContextStr SHA512Context;
typedef struct SHA512ContextStr SHA384Context;
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
typedef struct SEEDContextStr SEEDContext;
typedef struct ChaCha20ContextStr ChaCha20Context;
typedef struct ChaCha20Poly1305ContextStr ChaCha20Poly1305Context;
typedef struct Blake2bContextStr BLAKE2BContext;

View file

@ -17,13 +17,25 @@
#include <intrin.h> /* for _xgetbv() */
#endif
#if defined(_WIN64) && defined(__aarch64__)
#include <windows.h>
#endif
#if defined(DARWIN)
#include <TargetConditionals.h>
#endif
static PRCallOnceType coFreeblInit;
/* State variables. */
static PRBool aesni_support_ = PR_FALSE;
static PRBool clmul_support_ = PR_FALSE;
static PRBool sha_support_ = PR_FALSE;
static PRBool avx_support_ = PR_FALSE;
static PRBool avx2_support_ = PR_FALSE;
static PRBool ssse3_support_ = PR_FALSE;
static PRBool sse4_1_support_ = PR_FALSE;
static PRBool sse4_2_support_ = PR_FALSE;
static PRBool arm_neon_support_ = PR_FALSE;
static PRBool arm_aes_support_ = PR_FALSE;
static PRBool arm_sha1_support_ = PR_FALSE;
@ -35,6 +47,7 @@ static PRBool ppc_crypto_support_ = PR_FALSE;
/*
* Adapted from the example code in "How to detect New Instruction support in
* the 4th generation Intel Core processor family" by Max Locktyukhin.
* https://www.intel.com/content/dam/develop/external/us/en/documents/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf
*
* XGETBV:
* Reads an extended control register (XCR) specified by ECX into EDX:EAX.
@ -69,31 +82,64 @@ check_xcr0_ymm()
#define ECX_XSAVE (1 << 26)
#define ECX_OSXSAVE (1 << 27)
#define ECX_AVX (1 << 28)
#define EBX_AVX2 (1 << 5)
#define EBX_BMI1 (1 << 3)
#define EBX_BMI2 (1 << 8)
#define EBX_SHA (1 << 29)
#define ECX_FMA (1 << 12)
#define ECX_MOVBE (1 << 22)
#define ECX_SSSE3 (1 << 9)
#define ECX_SSE4_1 (1 << 19)
#define ECX_SSE4_2 (1 << 20)
#define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX)
#define AVX2_EBX_BITS (EBX_AVX2 | EBX_BMI1 | EBX_BMI2)
#define AVX2_ECX_BITS (ECX_FMA | ECX_MOVBE)
void
CheckX86CPUSupport()
{
unsigned long eax, ebx, ecx, edx;
unsigned long eax7, ebx7, ecx7, edx7;
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL");
char *disable_hw_sha = PR_GetEnvSecure("NSS_DISABLE_HW_SHA");
char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX");
char *disable_avx2 = PR_GetEnvSecure("NSS_DISABLE_AVX2");
char *disable_ssse3 = PR_GetEnvSecure("NSS_DISABLE_SSSE3");
char *disable_sse4_1 = PR_GetEnvSecure("NSS_DISABLE_SSE4_1");
char *disable_sse4_2 = PR_GetEnvSecure("NSS_DISABLE_SSE4_2");
freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
freebl_cpuid(7, &eax7, &ebx7, &ecx7, &edx7);
aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL);
clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL);
/* For AVX we check AVX, OSXSAVE, and XSAVE
* as well as XMM and YMM state. */
sha_support_ = (PRBool)((ebx7 & EBX_SHA) != 0 && disable_hw_sha == NULL);
/* For AVX we ensure that:
* - The AVX, OSXSAVE, and XSAVE bits of ECX from CPUID(EAX=1) are set, and
* - the SSE and AVX state bits of XCR0 are set (check_xcr0_ymm).
*/
avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() &&
disable_avx == NULL;
/* For AVX2 we ensure that:
* - AVX is supported,
* - the AVX2, BMI1, and BMI2 bits of EBX from CPUID(EAX=7) are set, and
* - the FMA, and MOVBE bits of ECX from CPUID(EAX=1) are set.
* We do not check for LZCNT support.
*/
avx2_support_ = (PRBool)(avx_support_ == PR_TRUE &&
(ebx7 & AVX2_EBX_BITS) == AVX2_EBX_BITS &&
(ecx & AVX2_ECX_BITS) == AVX2_ECX_BITS &&
disable_avx2 == NULL);
ssse3_support_ = (PRBool)((ecx & ECX_SSSE3) != 0 &&
disable_ssse3 == NULL);
sse4_1_support_ = (PRBool)((ecx & ECX_SSE4_1) != 0 &&
disable_sse4_1 == NULL);
sse4_2_support_ = (PRBool)((ecx & ECX_SSE4_2) != 0 &&
disable_sse4_2 == NULL);
}
#endif /* NSS_X86_OR_X64 */
/* clang-format off */
#if defined(__aarch64__) || defined(__arm__)
#if (defined(__aarch64__) || defined(__arm__)) && !defined(TARGET_OS_IPHONE)
#ifndef __has_include
#define __has_include(x) 0
#endif
@ -104,10 +150,26 @@ CheckX86CPUSupport()
#include <sys/auxv.h>
#endif
extern unsigned long getauxval(unsigned long type) __attribute__((weak));
#else
#elif defined(__arm__) || (!defined(__OpenBSD__) && !defined(_WIN64))
static unsigned long (*getauxval)(unsigned long) = NULL;
#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/
#if defined(__FreeBSD__) && !defined(__aarch64__) && __has_include(<sys/auxv.h>)
/* Avoid conflict with static declaration above */
#define getauxval freebl_getauxval
static unsigned long getauxval(unsigned long type)
{
/* Only AT_HWCAP* return unsigned long */
if (type != AT_HWCAP && type != AT_HWCAP2) {
return 0;
}
unsigned long ret = 0;
elf_aux_info(type, &ret, sizeof(ret));
return ret;
}
#endif
#ifndef AT_HWCAP2
#define AT_HWCAP2 26
#endif
@ -119,6 +181,8 @@ static unsigned long (*getauxval)(unsigned long) = NULL;
/* clang-format on */
#if defined(__aarch64__)
#if defined(__linux__)
// Defines from hwcap.h in Linux kernel - ARM64
#ifndef HWCAP_AES
#define HWCAP_AES (1 << 3)
@ -132,22 +196,81 @@ static unsigned long (*getauxval)(unsigned long) = NULL;
#ifndef HWCAP_SHA2
#define HWCAP_SHA2 (1 << 6)
#endif
#endif /* defined(__linux__) */
#if defined(__FreeBSD__)
#include <stdint.h>
#include <machine/armreg.h>
// Support for older version of armreg.h
#ifndef ID_AA64ISAR0_AES_VAL
#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
#endif
#ifndef ID_AA64ISAR0_SHA1_VAL
#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
#endif
#ifndef ID_AA64ISAR0_SHA2_VAL
#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
#endif
#endif /* defined(__FreeBSD__) */
#if defined(__OpenBSD__)
#include <sys/sysctl.h>
#include <machine/cpu.h>
#include <machine/armreg.h>
#endif /* defined(__OpenBSD__) */
void
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 defined(_WIN64)
BOOL arm_crypto_support = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
arm_aes_support_ = arm_crypto_support;
arm_pmull_support_ = arm_crypto_support;
arm_sha1_support_ = arm_crypto_support;
arm_sha2_support_ = arm_crypto_support;
#elif defined(__linux__)
if (getauxval) {
long hwcaps = getauxval(AT_HWCAP);
arm_aes_support_ = hwcaps & HWCAP_AES && disable_hw_aes == NULL;
arm_pmull_support_ = hwcaps & HWCAP_PMULL && disable_pmull == NULL;
arm_sha1_support_ = hwcaps & HWCAP_SHA1;
arm_sha2_support_ = hwcaps & HWCAP_SHA2;
arm_aes_support_ = (hwcaps & HWCAP_AES) == HWCAP_AES;
arm_pmull_support_ = (hwcaps & HWCAP_PMULL) == HWCAP_PMULL;
arm_sha1_support_ = (hwcaps & HWCAP_SHA1) == HWCAP_SHA1;
arm_sha2_support_ = (hwcaps & HWCAP_SHA2) == HWCAP_SHA2;
}
#elif defined(__FreeBSD__)
/* qemu-user does not support register access from userspace */
if (PR_GetEnvSecure("QEMU_EMULATING") == NULL) {
uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1);
arm_aes_support_ = ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE;
arm_pmull_support_ = ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_PMULL;
arm_sha1_support_ = ID_AA64ISAR0_SHA1_VAL(isar0) >= ID_AA64ISAR0_SHA1_BASE;
arm_sha2_support_ = ID_AA64ISAR0_SHA2_VAL(isar0) >= ID_AA64ISAR0_SHA2_BASE;
}
#elif defined(__OpenBSD__)
const int isar0_mib[] = { CTL_MACHDEP, CPU_ID_AA64ISAR0 };
uint64_t isar0;
size_t len = sizeof(isar0);
if (sysctl(isar0_mib, 2, &isar0, &len, NULL, 0) < 0)
return;
arm_aes_support_ = ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_BASE;
arm_pmull_support_ = ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_PMULL;
arm_sha1_support_ = ID_AA64ISAR0_SHA1(isar0) >= ID_AA64ISAR0_SHA1_BASE;
arm_sha2_support_ = ID_AA64ISAR0_SHA2(isar0) >= ID_AA64ISAR0_SHA2_BASE;
#elif defined(__ARM_FEATURE_CRYPTO)
/*
* Although no feature detection, default compiler option allows ARM
* Crypto Extension.
*/
arm_aes_support_ = PR_TRUE;
arm_pmull_support_ = PR_TRUE;
arm_sha1_support_ = PR_TRUE;
arm_sha2_support_ = PR_TRUE;
#endif
/* aarch64 must support NEON. */
arm_neon_support_ = disable_arm_neon == NULL;
arm_neon_support_ = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON") == NULL;
arm_aes_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_AES") == NULL;
arm_pmull_support_ &= PR_GetEnvSecure("NSS_DISABLE_PMULL") == NULL;
arm_sha1_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA1") == NULL;
arm_sha2_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA2") == NULL;
}
#endif /* defined(__aarch64__) */
@ -271,6 +394,8 @@ CheckARMSupport()
arm_sha2_support_ = hwcaps & HWCAP2_SHA2;
}
arm_neon_support_ = GetNeonSupport();
arm_sha1_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA1") == NULL;
arm_sha2_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA2") == NULL;
}
#endif /* defined(__arm__) */
@ -315,16 +440,36 @@ clmul_support()
return clmul_support_;
}
PRBool
sha_support()
{
return sha_support_;
}
PRBool
avx_support()
{
return avx_support_;
}
PRBool
avx2_support()
{
return avx2_support_;
}
PRBool
ssse3_support()
{
return ssse3_support_;
}
PRBool
sse4_1_support()
{
return sse4_1_support_;
}
PRBool
sse4_2_support()
{
return sse4_2_support_;
}
PRBool
arm_neon_support()
{
return arm_neon_support_;
@ -357,7 +502,18 @@ ppc_crypto_support()
#if defined(__powerpc__)
#ifndef __has_include
#define __has_include(x) 0
#endif
/* clang-format off */
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 12)
#if __has_include(<sys/auxv.h>)
#include <sys/auxv.h>
#endif
#elif (defined(__FreeBSD__) && __FreeBSD__ < 12)
#include <sys/sysctl.h>
#endif
// Defines from cputable.h in Linux kernel - PPC, letting us build on older kernels
#ifndef PPC_FEATURE2_VEC_CRYPTO
@ -369,10 +525,25 @@ CheckPPCSupport()
{
char *disable_hw_crypto = PR_GetEnvSecure("NSS_DISABLE_PPC_GHASH");
long hwcaps = getauxval(AT_HWCAP2);
unsigned long hwcaps = 0;
#if defined(__linux__)
#if __has_include(<sys/auxv.h>)
hwcaps = getauxval(AT_HWCAP2);
#endif
#elif defined(__FreeBSD__)
#if __FreeBSD__ >= 12
#if __has_include(<sys/auxv.h>)
elf_aux_info(AT_HWCAP2, &hwcaps, sizeof(hwcaps));
#endif
#else
size_t len = sizeof(hwcaps);
sysctlbyname("hw.cpu_features2", &hwcaps, &len, NULL, 0);
#endif
#endif
ppc_crypto_support_ = hwcaps & PPC_FEATURE2_VEC_CRYPTO && disable_hw_crypto == NULL;
}
/* clang-format on */
#endif /* __powerpc__ */

View file

@ -220,7 +220,7 @@ static const PRUint32 camellia_sp1110[256] = {
0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00,
0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100,
0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00,
0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
};
static const PRUint32 camellia_sp0222[256] = {
@ -287,7 +287,7 @@ static const PRUint32 camellia_sp0222[256] = {
0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6,
0x00777777, 0x00939393, 0x00868686, 0x00838383,
0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d,
0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
};
static const PRUint32 camellia_sp3033[256] = {
@ -354,7 +354,7 @@ static const PRUint32 camellia_sp3033[256] = {
0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd,
0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0,
0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f,
0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
};
static const PRUint32 camellia_sp4404[256] = {
@ -421,7 +421,7 @@ static const PRUint32 camellia_sp4404[256] = {
0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a,
0x49490049, 0x68680068, 0x38380038, 0xa4a400a4,
0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e,
0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
};
/**

View file

@ -0,0 +1,668 @@
# 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/.
# vs0 - vs15 : buffer for xor
# vs32 - vs47 (v0 - v15) : 4 "converted" states
# vs48 - vs51 (v16 - v19) : original state
# vs52 - vs55 (v20 - v23) : "converted" constants
# vs56 (v24) : "converted" counter
# vs57 (v25) : increment for "converted" counter
# vs60 - vs63 (v28 - v31) : constants for rotate left or vpermxor
#define r0 0
#define sp 1
#define r2 2
#define rSIZE 3
#define rDST 4
#define rSRC 5
#define rKEY 6
#define rNONCE 7
#define rCNTR 8
#define r9 9
#define r10 10
#define r11 11
#define r12 12
#define r13 13
#define r14 14
#define r15 15
#define r16 16
#define r17 17
#define r18 18
#define r19 19
#define r20 20
#define r21 21
#define r22 22
#define r23 23
#define r24 24
#define r25 25
#define r26 26
#define r27 27
#define r28 28
#define r29 29
#define r30 30
#define r31 31
#define v0 0
#define v1 1
#define v2 2
#define v3 3
#define v4 4
#define v5 5
#define v6 6
#define v7 7
#define v8 8
#define v9 9
#define v10 10
#define v11 11
#define v12 12
#define v13 13
#define v14 14
#define v15 15
#define v16 16
#define v17 17
#define v18 18
#define v19 19
#define v20 20
#define v21 21
#define v22 22
#define v23 23
#define v24 24
#define v25 25
#define v26 26
#define v27 27
#define v28 28
#define v29 29
#define v30 30
#define v31 31
#define vs0 0
#define vs1 1
#define vs2 2
#define vs3 3
#define vs4 4
#define vs5 5
#define vs6 6
#define vs7 7
#define vs8 8
#define vs9 9
#define vs10 10
#define vs11 11
#define vs12 12
#define vs13 13
#define vs14 14
#define vs15 15
#define vs16 16
#define vs17 17
#define vs18 18
#define vs19 19
#define vs20 20
#define vs21 21
#define vs22 22
#define vs23 23
#define vs24 24
#define vs25 25
#define vs26 26
#define vs27 27
#define vs28 28
#define vs29 29
#define vs30 30
#define vs31 31
#define vs32 32
#define vs33 33
#define vs34 34
#define vs35 35
#define vs36 36
#define vs37 37
#define vs38 38
#define vs39 39
#define vs40 40
#define vs41 41
#define vs42 42
#define vs43 43
#define vs44 44
#define vs45 45
#define vs46 46
#define vs47 47
#define vs48 48
#define vs49 49
#define vs50 50
#define vs51 51
#define vs52 52
#define vs53 53
#define vs54 54
#define vs55 55
#define vs56 56
#define vs57 57
#define vs58 58
#define vs59 59
#define vs60 60
#define vs61 61
#define vs62 62
#define vs63 63
.abiversion 2
.section ".data"
.align 5
lblock: .skip 256
cnts0: .long 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
cnts1: .long 0x61707865, 0x61707865, 0x61707865, 0x61707865
cnts2: .long 0x3320646e, 0x3320646e, 0x3320646e, 0x3320646e
cnts3: .long 0x79622d32, 0x79622d32, 0x79622d32, 0x79622d32
cnts4: .long 0x6b206574, 0x6b206574, 0x6b206574, 0x6b206574
st4: .long 0, 0, 0, 0
cntr: .long 0, 0, 0, 0
incr: .long 4, 4, 4, 4
rotl1: .long 0x22330011, 0x66774455, 0xAABB8899, 0xEEFFCCDD
rotl2: .long 12, 12, 12, 12
rotl3: .long 0x11223300, 0x55667744, 0x99AABB88, 0xDDEEFFCC
rotl4: .long 7, 7, 7, 7
.section ".text"
.align 5
.globl chacha20vsx
.type chacha20vsx, @function
chacha20vsx:
# prologue
addis 2, r12, .TOC.-chacha20vsx@ha
addi 2, 2, .TOC.-chacha20vsx@l
.localentry chacha20vsx, .-chacha20vsx
std r14, -8(sp)
std r15, -16(sp)
std r16, -24(sp)
std r17, -32(sp)
std r18, -40(sp)
std r19, -48(sp)
std r20, -56(sp)
std r21, -64(sp)
std r22, -72(sp)
std r23, -80(sp)
std r24, -88(sp)
std r25, -96(sp)
std r26, -104(sp)
std r27, -112(sp)
std r28, -120(sp)
std r29, -128(sp)
std r30, -136(sp)
std r31, -144(sp)
addi r14, sp, -160
li r16, -16
li r17, -32
li r18, -48
li r19, -64
li r20, -80
li r21, -96
li r22, -112
li r23, -128
li r24, -144
li r25, -160
li r26, -176
li r27, -192
li r28, -208
# save f14, f15
stxvw4x vs14, 0, r14
stxvw4x vs15, r16, r14
# save v20 - v31
stxvw4x vs52, r17, r14
stxvw4x vs53, r18, r14
stxvw4x vs54, r19, r14
stxvw4x vs55, r20, r14
stxvw4x vs56, r21, r14
stxvw4x vs57, r22, r14
stxvw4x vs58, r23, r14
stxvw4x vs59, r24, r14
stxvw4x vs60, r25, r14
stxvw4x vs61, r26, r14
stxvw4x vs62, r27, r14
stxvw4x vs63, r28, r14
# offset in src/dst
li r17, 16
li r18, 32
li r19, 48
li r20, 64
li r21, 80
li r22, 96
li r23, 112
li r24, 128
li r25, 144
li r26, 160
li r27, 176
li r28, 192
li r29, 208
li r30, 224
li r31, 240
# load const's address
addis r14, 2, cnts0@toc@ha
addi r14, r14, cnts0@toc@l
# save nonce to st4
lwz r15, 0(rNONCE)
stw r15, 84(r14)
lwz r15, 4(rNONCE)
stw r15, 88(r14)
lwz r15, 8(rNONCE)
stw r15, 92(r14)
# load state to vectors
lxvw4x vs48, 0, r14
lxvw4x vs49, 0, rKEY
lxvw4x vs50, r17, rKEY
lxvw4x vs51, r21, r14
# load consts for x4 rounds
lxvw4x vs52, r17, r14
lxvw4x vs53, r18, r14
lxvw4x vs54, r19, r14
lxvw4x vs55, r20, r14
# counter
stw rCNTR, 96(r14)
addi rCNTR, rCNTR, 1
stw rCNTR, 100(r14)
addi rCNTR, rCNTR, 1
stw rCNTR, 104(r14)
addi rCNTR, rCNTR, 1
stw rCNTR, 108(r14)
lxvw4x vs56, r22, r14
# load increment
lxvw4x vs57, r23, r14
# load rotl to vectors
lxvw4x vs60, r24, r14
lxvw4x vs61, r25, r14
lxvw4x vs62, r26, r14
lxvw4x vs63, r27, r14
# counter for loop = size/256
li r15, 256
divdu. r16, rSIZE, r15
beq lastblock
mtctr r16
mainloop:
# init 16 vectors (4 states x4)
vor v0, v20, v20
vor v1, v21, v21
vor v2, v22, v22
vor v3, v23, v23
vspltw v4, v17, v0
vspltw v5, v17, v1
vspltw v6, v17, v2
vspltw v7, v17, v3
vspltw v8, v18, v0
vspltw v9, v18, v1
vspltw v10, v18, v2
vspltw v11, v18, v3
vor v12, v24, v24
vspltw v13, v19, v1
vspltw v14, v19, v2
vspltw v15, v19, v3
.macro _plus a b_y b_x
vadduwm \a, \a, \b_y*4+(\b_x)%4
vadduwm \a+1, \a+1, \b_y*4+(\b_x+1)%4
vadduwm \a+2, \a+2, \b_y*4+(\b_x+2)%4
vadduwm \a+3, \a+3, \b_y*4+(\b_x+3)%4
.endm
.macro _xor a b_y b_x
vxor \a, \a, \b_y*4+(\b_x)%4
vxor \a+1, \a+1, \b_y*4+(\b_x+1)%4
vxor \a+2, \a+2, \b_y*4+(\b_x+2)%4
vxor \a+3, \a+3, \b_y*4+(\b_x+3)%4
.endm
.macro _rotl a b
vrlw \a, \a, \b
vrlw \a+1, \a+1, \b
vrlw \a+2, \a+2, \b
vrlw \a+3, \a+3, \b
.endm
.macro _pxor a b_y b_x c
vpermxor \a, \a, \b_y*4+(\b_x)%4, \c
vpermxor \a+1, \a+1, \b_y*4+(\b_x+1)%4, \c
vpermxor \a+2, \a+2, \b_y*4+(\b_x+2)%4, \c
vpermxor \a+3, \a+3, \b_y*4+(\b_x+3)%4, \c
.endm
# 00 01 02 03
# 04 05 06 07
# 08 09 10 11
# 12 13 14 15
.macro doubleround
# column round
_plus v0, v1, v0 # a+=b
_pxor v12, v0, v0, v28 # d^=a; d<<<=16
_plus v8, v3, v0 # c+=d
_xor v4, v2, v0 # b^=c
_rotl v4, v29 # b<<<=12
_plus v0, v1, v0 # a+=b
_pxor v12, v0, v0, v30 # d^=a; d<<<=8
_plus v8, v3, v0 # c+=d
_xor v4, v2, v0 # b^=c
_rotl v4, v31 # b<<<=7
# diagonal round
_plus v0, v1, v1 # a+=b
_pxor v12, v0, v1, v28 # d^=a; d<<<=16
_plus v8, v3, v1 # c+=d
_xor v4, v2, v1 # b^=c
_rotl v4, v29 # b<<<=12
_plus v0, v1, v1 # a+=b
_pxor v12, v0, v1, v30 # d^=a; d<<<=8
_plus v8, v3, v1 # c+=d
_xor v4, v2, v1 # b^=c
_rotl v4, v31 # b<<<=7
.endm
doubleround # 1
doubleround # 2
doubleround # 3
doubleround # 4
doubleround # 5
doubleround # 6
doubleround # 7
doubleround # 8
doubleround # 9
doubleround # 10
# counter += original counter
vadduwm v12, v12, v24
.macro convert a
vmrgew 26, 0+\a, 1+\a
vmrgew 27, 2+\a, 3+\a
vmrgow 0+\a, 0+\a, 1+\a
vmrgow 2+\a, 2+\a, 3+\a
xxmrghd 33+\a, 32+\a, 34+\a
xxmrgld 35+\a, 32+\a, 34+\a
xxmrghd 32+\a, 58, 59
xxmrgld 34+\a, 58, 59
.endm
convert 0
convert 4
convert 8
convert 12
.macro addition a
vadduwm 0+\a, 0+\a, 16
vadduwm 4+\a, 4+\a, 17
vadduwm 8+\a, 8+\a, 18
vadduwm 12+\a, 12+\a, 19
.endm
addition 0
addition 1
addition 2
addition 3
# load text/cipher
lxvw4x vs0, 0, rSRC
lxvw4x vs1, r17, rSRC
lxvw4x vs2, r18, rSRC
lxvw4x vs3, r19, rSRC
lxvw4x vs4, r20, rSRC
lxvw4x vs5, r21, rSRC
lxvw4x vs6, r22, rSRC
lxvw4x vs7, r23, rSRC
lxvw4x vs8, r24, rSRC
lxvw4x vs9, r25, rSRC
lxvw4x vs10, r26, rSRC
lxvw4x vs11, r27, rSRC
lxvw4x vs12, r28, rSRC
lxvw4x vs13, r29, rSRC
lxvw4x vs14, r30, rSRC
lxvw4x vs15, r31, rSRC
# xor (encrypt/decrypt)
xxlxor vs0, vs0, vs32
xxlxor vs1, vs1, vs36
xxlxor vs2, vs2, vs40
xxlxor vs3, vs3, vs44
xxlxor vs4, vs4, vs33
xxlxor vs5, vs5, vs37
xxlxor vs6, vs6, vs41
xxlxor vs7, vs7, vs45
xxlxor vs8, vs8, vs34
xxlxor vs9, vs9, vs38
xxlxor vs10, vs10, vs42
xxlxor vs11, vs11, vs46
xxlxor vs12, vs12, vs35
xxlxor vs13, vs13, vs39
xxlxor vs14, vs14, vs43
xxlxor vs15, vs15, vs47
# store cipher/text
stxvw4x vs0, 0, rDST
stxvw4x vs1, r17, rDST
stxvw4x vs2, r18, rDST
stxvw4x vs3, r19, rDST
stxvw4x vs4, r20, rDST
stxvw4x vs5, r21, rDST
stxvw4x vs6, r22, rDST
stxvw4x vs7, r23, rDST
stxvw4x vs8, r24, rDST
stxvw4x vs9, r25, rDST
stxvw4x vs10, r26, rDST
stxvw4x vs11, r27, rDST
stxvw4x vs12, r28, rDST
stxvw4x vs13, r29, rDST
stxvw4x vs14, r30, rDST
stxvw4x vs15, r31, rDST
# src/dst increment
addi rSRC, rSRC, 256
addi rDST, rDST, 256
# counter increment
vadduwm v24, v24, v25
bdnz mainloop
lastblock:
# reminder
mulld r16, r16, r15
subf. r16, r16, rSIZE
# check reminder
beq exitsub
addi r14, r14, -256
# last block x4
# init 16 vectors (4 states x4)
vor v0, v20, v20
vor v1, v21, v21
vor v2, v22, v22
vor v3, v23, v23
vspltw v4, v17, v0
vspltw v5, v17, v1
vspltw v6, v17, v2
vspltw v7, v17, v3
vspltw v8, v18, v0
vspltw v9, v18, v1
vspltw v10, v18, v2
vspltw v11, v18, v3
vor v12, v24, v24
vspltw v13, v19, v1
vspltw v14, v19, v2
vspltw v15, v19, v3
doubleround # 1
doubleround # 2
doubleround # 3
doubleround # 4
doubleround # 5
doubleround # 6
doubleround # 7
doubleround # 8
doubleround # 9
doubleround # 10
vadduwm v12, v12, v24
convert 0
convert 4
convert 8
convert 12
addition 0
addition 1
addition 2
addition 3
# store vectors
stxvw4x vs32, 0, r14
stxvw4x vs36, r17, r14
stxvw4x vs40, r18, r14
stxvw4x vs44, r19, r14
stxvw4x vs33, r20, r14
stxvw4x vs37, r21, r14
stxvw4x vs41, r22, r14
stxvw4x vs45, r23, r14
stxvw4x vs34, r24, r14
stxvw4x vs38, r25, r14
stxvw4x vs42, r26, r14
stxvw4x vs46, r27, r14
stxvw4x vs35, r28, r14
stxvw4x vs39, r29, r14
stxvw4x vs43, r30, r14
stxvw4x vs47, r31, r14
mtctr r16
addi rSIZE, r14, -1
addi rSRC, rSRC, -1
addi rDST, rDST, -1
xorlast:
lbzu r15, 1(rSIZE)
lbzu r16, 1(rSRC)
xor r15, r15, r16
stbu r15, 1(rDST)
bdnz xorlast
# zeroing last block
xxlxor vs0, vs0, vs0
stxvw4x vs0, 0, r14
stxvw4x vs0, r17, r14
stxvw4x vs0, r18, r14
stxvw4x vs0, r19, r14
stxvw4x vs0, r20, r14
stxvw4x vs0, r21, r14
stxvw4x vs0, r22, r14
stxvw4x vs0, r23, r14
stxvw4x vs0, r24, r14
stxvw4x vs0, r25, r14
stxvw4x vs0, r26, r14
stxvw4x vs0, r27, r14
stxvw4x vs0, r28, r14
stxvw4x vs0, r29, r14
stxvw4x vs0, r30, r14
stxvw4x vs0, r31, r14
exitsub:
# zeroing volatile registers
xxlxor vs0, vs0, vs0
xxlxor vs1, vs1, vs1
xxlxor vs2, vs2, vs2
xxlxor vs3, vs3, vs3
xxlxor vs4, vs4, vs4
xxlxor vs5, vs5, vs5
xxlxor vs6, vs6, vs6
xxlxor vs7, vs7, vs7
xxlxor vs8, vs8, vs8
xxlxor vs9, vs9, vs9
xxlxor vs10, vs10, vs10
xxlxor vs11, vs11, vs11
xxlxor vs12, vs12, vs12
xxlxor vs13, vs13, vs13
xxlxor vs32, vs32, vs32
xxlxor vs33, vs33, vs33
xxlxor vs34, vs34, vs34
xxlxor vs35, vs35, vs35
xxlxor vs36, vs36, vs36
xxlxor vs37, vs37, vs37
xxlxor vs38, vs38, vs38
xxlxor vs39, vs39, vs39
xxlxor vs40, vs40, vs40
xxlxor vs41, vs41, vs41
xxlxor vs42, vs42, vs42
xxlxor vs43, vs43, vs43
xxlxor vs44, vs44, vs44
xxlxor vs45, vs45, vs45
xxlxor vs46, vs46, vs46
xxlxor vs47, vs47, vs47
xxlxor vs48, vs48, vs48
xxlxor vs49, vs49, vs49
xxlxor vs50, vs50, vs50
xxlxor vs51, vs51, vs51
li rSIZE, 0
li rDST, 0
li rSRC, 0
li rKEY, 0
li rNONCE, 0
li rCNTR, 0
# epilogue
addi r14, sp, -160
li r16, -16
li r17, -32
li r18, -48
li r19, -64
li r20, -80
li r21, -96
li r22, -112
li r23, -128
li r24, -144
li r25, -160
li r26, -176
li r27, -192
li r28, -208
# load f14, f15
lxvw4x vs14, 0, r14
lxvw4x vs15, r16, r14
# load v20 - v31
lxvw4x vs52, r17, r14
lxvw4x vs53, r18, r14
lxvw4x vs54, r19, r14
lxvw4x vs55, r20, r14
lxvw4x vs56, r21, r14
lxvw4x vs57, r22, r14
lxvw4x vs58, r23, r14
lxvw4x vs59, r24, r14
lxvw4x vs60, r25, r14
lxvw4x vs61, r26, r14
lxvw4x vs62, r27, r14
lxvw4x vs63, r28, r14
ld r14, -8(sp)
ld r15, -16(sp)
ld r16, -24(sp)
ld r17, -32(sp)
ld r18, -40(sp)
ld r19, -48(sp)
ld r20, -56(sp)
ld r21, -64(sp)
ld r22, -72(sp)
ld r23, -80(sp)
ld r24, -88(sp)
ld r25, -96(sp)
ld r26, -104(sp)
ld r27, -112(sp)
ld r28, -120(sp)
ld r29, -128(sp)
ld r30, -136(sp)
ld r31, -144(sp)
blr

View file

@ -0,0 +1,588 @@
/* MIT License
*
* Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation
*
* 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.
*/
#include "Hacl_Chacha20Poly1305_32.h"
/* Forward declaration from chacha20-ppc64le.S */
void chacha20vsx(uint32_t len, uint8_t *output, uint8_t *block, uint8_t *k,
uint8_t *nonce, uint32_t ctr);
static inline void
poly1305_padded_32(uint64_t *ctx, uint32_t len, uint8_t *text)
{
uint32_t n = len / (uint32_t)16U;
uint32_t r = len % (uint32_t)16U;
uint8_t *blocks = text;
uint8_t *rem = text + n * (uint32_t)16U;
uint64_t *pre0 = ctx + (uint32_t)5U;
uint64_t *acc0 = ctx;
uint32_t nb = n * (uint32_t)16U / (uint32_t)16U;
uint32_t rem1 = n * (uint32_t)16U % (uint32_t)16U;
for (uint32_t i = (uint32_t)0U; i < nb; i++) {
uint8_t *block = blocks + i * (uint32_t)16U;
uint64_t e[5U] = { 0U };
uint64_t u0 = load64_le(block);
uint64_t lo = u0;
uint64_t u = load64_le(block + (uint32_t)8U);
uint64_t hi = u;
uint64_t f0 = lo;
uint64_t f1 = hi;
uint64_t f010 = f0 & (uint64_t)0x3ffffffU;
uint64_t f110 = f0 >> (uint32_t)26U & (uint64_t)0x3ffffffU;
uint64_t f20 = f0 >> (uint32_t)52U | (f1 & (uint64_t)0x3fffU) << (uint32_t)12U;
uint64_t f30 = f1 >> (uint32_t)14U & (uint64_t)0x3ffffffU;
uint64_t f40 = f1 >> (uint32_t)40U;
uint64_t f01 = f010;
uint64_t f111 = f110;
uint64_t f2 = f20;
uint64_t f3 = f30;
uint64_t f41 = f40;
e[0U] = f01;
e[1U] = f111;
e[2U] = f2;
e[3U] = f3;
e[4U] = f41;
uint64_t b = (uint64_t)0x1000000U;
uint64_t mask = b;
uint64_t f4 = e[4U];
e[4U] = f4 | mask;
uint64_t *r1 = pre0;
uint64_t *r5 = pre0 + (uint32_t)5U;
uint64_t r0 = r1[0U];
uint64_t r11 = r1[1U];
uint64_t r2 = r1[2U];
uint64_t r3 = r1[3U];
uint64_t r4 = r1[4U];
uint64_t r51 = r5[1U];
uint64_t r52 = r5[2U];
uint64_t r53 = r5[3U];
uint64_t r54 = r5[4U];
uint64_t f10 = e[0U];
uint64_t f11 = e[1U];
uint64_t f12 = e[2U];
uint64_t f13 = e[3U];
uint64_t f14 = e[4U];
uint64_t a0 = acc0[0U];
uint64_t a1 = acc0[1U];
uint64_t a2 = acc0[2U];
uint64_t a3 = acc0[3U];
uint64_t a4 = acc0[4U];
uint64_t a01 = a0 + f10;
uint64_t a11 = a1 + f11;
uint64_t a21 = a2 + f12;
uint64_t a31 = a3 + f13;
uint64_t a41 = a4 + f14;
uint64_t a02 = r0 * a01;
uint64_t a12 = r11 * a01;
uint64_t a22 = r2 * a01;
uint64_t a32 = r3 * a01;
uint64_t a42 = r4 * a01;
uint64_t a03 = a02 + r54 * a11;
uint64_t a13 = a12 + r0 * a11;
uint64_t a23 = a22 + r11 * a11;
uint64_t a33 = a32 + r2 * a11;
uint64_t a43 = a42 + r3 * a11;
uint64_t a04 = a03 + r53 * a21;
uint64_t a14 = a13 + r54 * a21;
uint64_t a24 = a23 + r0 * a21;
uint64_t a34 = a33 + r11 * a21;
uint64_t a44 = a43 + r2 * a21;
uint64_t a05 = a04 + r52 * a31;
uint64_t a15 = a14 + r53 * a31;
uint64_t a25 = a24 + r54 * a31;
uint64_t a35 = a34 + r0 * a31;
uint64_t a45 = a44 + r11 * a31;
uint64_t a06 = a05 + r51 * a41;
uint64_t a16 = a15 + r52 * a41;
uint64_t a26 = a25 + r53 * a41;
uint64_t a36 = a35 + r54 * a41;
uint64_t a46 = a45 + r0 * a41;
uint64_t t0 = a06;
uint64_t t1 = a16;
uint64_t t2 = a26;
uint64_t t3 = a36;
uint64_t t4 = a46;
uint64_t mask26 = (uint64_t)0x3ffffffU;
uint64_t z0 = t0 >> (uint32_t)26U;
uint64_t z1 = t3 >> (uint32_t)26U;
uint64_t x0 = t0 & mask26;
uint64_t x3 = t3 & mask26;
uint64_t x1 = t1 + z0;
uint64_t x4 = t4 + z1;
uint64_t z01 = x1 >> (uint32_t)26U;
uint64_t z11 = x4 >> (uint32_t)26U;
uint64_t t = z11 << (uint32_t)2U;
uint64_t z12 = z11 + t;
uint64_t x11 = x1 & mask26;
uint64_t x41 = x4 & mask26;
uint64_t x2 = t2 + z01;
uint64_t x01 = x0 + z12;
uint64_t z02 = x2 >> (uint32_t)26U;
uint64_t z13 = x01 >> (uint32_t)26U;
uint64_t x21 = x2 & mask26;
uint64_t x02 = x01 & mask26;
uint64_t x31 = x3 + z02;
uint64_t x12 = x11 + z13;
uint64_t z03 = x31 >> (uint32_t)26U;
uint64_t x32 = x31 & mask26;
uint64_t x42 = x41 + z03;
uint64_t o0 = x02;
uint64_t o1 = x12;
uint64_t o2 = x21;
uint64_t o3 = x32;
uint64_t o4 = x42;
acc0[0U] = o0;
acc0[1U] = o1;
acc0[2U] = o2;
acc0[3U] = o3;
acc0[4U] = o4;
}
if (rem1 > (uint32_t)0U) {
uint8_t *last = blocks + nb * (uint32_t)16U;
uint64_t e[5U] = { 0U };
uint8_t tmp[16U] = { 0U };
memcpy(tmp, last, rem1 * sizeof(last[0U]));
uint64_t u0 = load64_le(tmp);
uint64_t lo = u0;
uint64_t u = load64_le(tmp + (uint32_t)8U);
uint64_t hi = u;
uint64_t f0 = lo;
uint64_t f1 = hi;
uint64_t f010 = f0 & (uint64_t)0x3ffffffU;
uint64_t f110 = f0 >> (uint32_t)26U & (uint64_t)0x3ffffffU;
uint64_t f20 = f0 >> (uint32_t)52U | (f1 & (uint64_t)0x3fffU) << (uint32_t)12U;
uint64_t f30 = f1 >> (uint32_t)14U & (uint64_t)0x3ffffffU;
uint64_t f40 = f1 >> (uint32_t)40U;
uint64_t f01 = f010;
uint64_t f111 = f110;
uint64_t f2 = f20;
uint64_t f3 = f30;
uint64_t f4 = f40;
e[0U] = f01;
e[1U] = f111;
e[2U] = f2;
e[3U] = f3;
e[4U] = f4;
uint64_t b = (uint64_t)1U << rem1 * (uint32_t)8U % (uint32_t)26U;
uint64_t mask = b;
uint64_t fi = e[rem1 * (uint32_t)8U / (uint32_t)26U];
e[rem1 * (uint32_t)8U / (uint32_t)26U] = fi | mask;
uint64_t *r1 = pre0;
uint64_t *r5 = pre0 + (uint32_t)5U;
uint64_t r0 = r1[0U];
uint64_t r11 = r1[1U];
uint64_t r2 = r1[2U];
uint64_t r3 = r1[3U];
uint64_t r4 = r1[4U];
uint64_t r51 = r5[1U];
uint64_t r52 = r5[2U];
uint64_t r53 = r5[3U];
uint64_t r54 = r5[4U];
uint64_t f10 = e[0U];
uint64_t f11 = e[1U];
uint64_t f12 = e[2U];
uint64_t f13 = e[3U];
uint64_t f14 = e[4U];
uint64_t a0 = acc0[0U];
uint64_t a1 = acc0[1U];
uint64_t a2 = acc0[2U];
uint64_t a3 = acc0[3U];
uint64_t a4 = acc0[4U];
uint64_t a01 = a0 + f10;
uint64_t a11 = a1 + f11;
uint64_t a21 = a2 + f12;
uint64_t a31 = a3 + f13;
uint64_t a41 = a4 + f14;
uint64_t a02 = r0 * a01;
uint64_t a12 = r11 * a01;
uint64_t a22 = r2 * a01;
uint64_t a32 = r3 * a01;
uint64_t a42 = r4 * a01;
uint64_t a03 = a02 + r54 * a11;
uint64_t a13 = a12 + r0 * a11;
uint64_t a23 = a22 + r11 * a11;
uint64_t a33 = a32 + r2 * a11;
uint64_t a43 = a42 + r3 * a11;
uint64_t a04 = a03 + r53 * a21;
uint64_t a14 = a13 + r54 * a21;
uint64_t a24 = a23 + r0 * a21;
uint64_t a34 = a33 + r11 * a21;
uint64_t a44 = a43 + r2 * a21;
uint64_t a05 = a04 + r52 * a31;
uint64_t a15 = a14 + r53 * a31;
uint64_t a25 = a24 + r54 * a31;
uint64_t a35 = a34 + r0 * a31;
uint64_t a45 = a44 + r11 * a31;
uint64_t a06 = a05 + r51 * a41;
uint64_t a16 = a15 + r52 * a41;
uint64_t a26 = a25 + r53 * a41;
uint64_t a36 = a35 + r54 * a41;
uint64_t a46 = a45 + r0 * a41;
uint64_t t0 = a06;
uint64_t t1 = a16;
uint64_t t2 = a26;
uint64_t t3 = a36;
uint64_t t4 = a46;
uint64_t mask26 = (uint64_t)0x3ffffffU;
uint64_t z0 = t0 >> (uint32_t)26U;
uint64_t z1 = t3 >> (uint32_t)26U;
uint64_t x0 = t0 & mask26;
uint64_t x3 = t3 & mask26;
uint64_t x1 = t1 + z0;
uint64_t x4 = t4 + z1;
uint64_t z01 = x1 >> (uint32_t)26U;
uint64_t z11 = x4 >> (uint32_t)26U;
uint64_t t = z11 << (uint32_t)2U;
uint64_t z12 = z11 + t;
uint64_t x11 = x1 & mask26;
uint64_t x41 = x4 & mask26;
uint64_t x2 = t2 + z01;
uint64_t x01 = x0 + z12;
uint64_t z02 = x2 >> (uint32_t)26U;
uint64_t z13 = x01 >> (uint32_t)26U;
uint64_t x21 = x2 & mask26;
uint64_t x02 = x01 & mask26;
uint64_t x31 = x3 + z02;
uint64_t x12 = x11 + z13;
uint64_t z03 = x31 >> (uint32_t)26U;
uint64_t x32 = x31 & mask26;
uint64_t x42 = x41 + z03;
uint64_t o0 = x02;
uint64_t o1 = x12;
uint64_t o2 = x21;
uint64_t o3 = x32;
uint64_t o4 = x42;
acc0[0U] = o0;
acc0[1U] = o1;
acc0[2U] = o2;
acc0[3U] = o3;
acc0[4U] = o4;
}
uint8_t tmp[16U] = { 0U };
memcpy(tmp, rem, r * sizeof(rem[0U]));
if (r > (uint32_t)0U) {
uint64_t *pre = ctx + (uint32_t)5U;
uint64_t *acc = ctx;
uint64_t e[5U] = { 0U };
uint64_t u0 = load64_le(tmp);
uint64_t lo = u0;
uint64_t u = load64_le(tmp + (uint32_t)8U);
uint64_t hi = u;
uint64_t f0 = lo;
uint64_t f1 = hi;
uint64_t f010 = f0 & (uint64_t)0x3ffffffU;
uint64_t f110 = f0 >> (uint32_t)26U & (uint64_t)0x3ffffffU;
uint64_t f20 = f0 >> (uint32_t)52U | (f1 & (uint64_t)0x3fffU) << (uint32_t)12U;
uint64_t f30 = f1 >> (uint32_t)14U & (uint64_t)0x3ffffffU;
uint64_t f40 = f1 >> (uint32_t)40U;
uint64_t f01 = f010;
uint64_t f111 = f110;
uint64_t f2 = f20;
uint64_t f3 = f30;
uint64_t f41 = f40;
e[0U] = f01;
e[1U] = f111;
e[2U] = f2;
e[3U] = f3;
e[4U] = f41;
uint64_t b = (uint64_t)0x1000000U;
uint64_t mask = b;
uint64_t f4 = e[4U];
e[4U] = f4 | mask;
uint64_t *r1 = pre;
uint64_t *r5 = pre + (uint32_t)5U;
uint64_t r0 = r1[0U];
uint64_t r11 = r1[1U];
uint64_t r2 = r1[2U];
uint64_t r3 = r1[3U];
uint64_t r4 = r1[4U];
uint64_t r51 = r5[1U];
uint64_t r52 = r5[2U];
uint64_t r53 = r5[3U];
uint64_t r54 = r5[4U];
uint64_t f10 = e[0U];
uint64_t f11 = e[1U];
uint64_t f12 = e[2U];
uint64_t f13 = e[3U];
uint64_t f14 = e[4U];
uint64_t a0 = acc[0U];
uint64_t a1 = acc[1U];
uint64_t a2 = acc[2U];
uint64_t a3 = acc[3U];
uint64_t a4 = acc[4U];
uint64_t a01 = a0 + f10;
uint64_t a11 = a1 + f11;
uint64_t a21 = a2 + f12;
uint64_t a31 = a3 + f13;
uint64_t a41 = a4 + f14;
uint64_t a02 = r0 * a01;
uint64_t a12 = r11 * a01;
uint64_t a22 = r2 * a01;
uint64_t a32 = r3 * a01;
uint64_t a42 = r4 * a01;
uint64_t a03 = a02 + r54 * a11;
uint64_t a13 = a12 + r0 * a11;
uint64_t a23 = a22 + r11 * a11;
uint64_t a33 = a32 + r2 * a11;
uint64_t a43 = a42 + r3 * a11;
uint64_t a04 = a03 + r53 * a21;
uint64_t a14 = a13 + r54 * a21;
uint64_t a24 = a23 + r0 * a21;
uint64_t a34 = a33 + r11 * a21;
uint64_t a44 = a43 + r2 * a21;
uint64_t a05 = a04 + r52 * a31;
uint64_t a15 = a14 + r53 * a31;
uint64_t a25 = a24 + r54 * a31;
uint64_t a35 = a34 + r0 * a31;
uint64_t a45 = a44 + r11 * a31;
uint64_t a06 = a05 + r51 * a41;
uint64_t a16 = a15 + r52 * a41;
uint64_t a26 = a25 + r53 * a41;
uint64_t a36 = a35 + r54 * a41;
uint64_t a46 = a45 + r0 * a41;
uint64_t t0 = a06;
uint64_t t1 = a16;
uint64_t t2 = a26;
uint64_t t3 = a36;
uint64_t t4 = a46;
uint64_t mask26 = (uint64_t)0x3ffffffU;
uint64_t z0 = t0 >> (uint32_t)26U;
uint64_t z1 = t3 >> (uint32_t)26U;
uint64_t x0 = t0 & mask26;
uint64_t x3 = t3 & mask26;
uint64_t x1 = t1 + z0;
uint64_t x4 = t4 + z1;
uint64_t z01 = x1 >> (uint32_t)26U;
uint64_t z11 = x4 >> (uint32_t)26U;
uint64_t t = z11 << (uint32_t)2U;
uint64_t z12 = z11 + t;
uint64_t x11 = x1 & mask26;
uint64_t x41 = x4 & mask26;
uint64_t x2 = t2 + z01;
uint64_t x01 = x0 + z12;
uint64_t z02 = x2 >> (uint32_t)26U;
uint64_t z13 = x01 >> (uint32_t)26U;
uint64_t x21 = x2 & mask26;
uint64_t x02 = x01 & mask26;
uint64_t x31 = x3 + z02;
uint64_t x12 = x11 + z13;
uint64_t z03 = x31 >> (uint32_t)26U;
uint64_t x32 = x31 & mask26;
uint64_t x42 = x41 + z03;
uint64_t o0 = x02;
uint64_t o1 = x12;
uint64_t o2 = x21;
uint64_t o3 = x32;
uint64_t o4 = x42;
acc[0U] = o0;
acc[1U] = o1;
acc[2U] = o2;
acc[3U] = o3;
acc[4U] = o4;
return;
}
}
static inline void
poly1305_do_32(
uint8_t *k,
uint32_t aadlen,
uint8_t *aad,
uint32_t mlen,
uint8_t *m,
uint8_t *out)
{
uint64_t ctx[25U] = { 0U };
uint8_t block[16U] = { 0U };
Hacl_Poly1305_32_poly1305_init(ctx, k);
poly1305_padded_32(ctx, aadlen, aad);
poly1305_padded_32(ctx, mlen, m);
store64_le(block, (uint64_t)aadlen);
store64_le(block + (uint32_t)8U, (uint64_t)mlen);
uint64_t *pre = ctx + (uint32_t)5U;
uint64_t *acc = ctx;
uint64_t e[5U] = { 0U };
uint64_t u0 = load64_le(block);
uint64_t lo = u0;
uint64_t u = load64_le(block + (uint32_t)8U);
uint64_t hi = u;
uint64_t f0 = lo;
uint64_t f1 = hi;
uint64_t f010 = f0 & (uint64_t)0x3ffffffU;
uint64_t f110 = f0 >> (uint32_t)26U & (uint64_t)0x3ffffffU;
uint64_t f20 = f0 >> (uint32_t)52U | (f1 & (uint64_t)0x3fffU) << (uint32_t)12U;
uint64_t f30 = f1 >> (uint32_t)14U & (uint64_t)0x3ffffffU;
uint64_t f40 = f1 >> (uint32_t)40U;
uint64_t f01 = f010;
uint64_t f111 = f110;
uint64_t f2 = f20;
uint64_t f3 = f30;
uint64_t f41 = f40;
e[0U] = f01;
e[1U] = f111;
e[2U] = f2;
e[3U] = f3;
e[4U] = f41;
uint64_t b = (uint64_t)0x1000000U;
uint64_t mask = b;
uint64_t f4 = e[4U];
e[4U] = f4 | mask;
uint64_t *r = pre;
uint64_t *r5 = pre + (uint32_t)5U;
uint64_t r0 = r[0U];
uint64_t r1 = r[1U];
uint64_t r2 = r[2U];
uint64_t r3 = r[3U];
uint64_t r4 = r[4U];
uint64_t r51 = r5[1U];
uint64_t r52 = r5[2U];
uint64_t r53 = r5[3U];
uint64_t r54 = r5[4U];
uint64_t f10 = e[0U];
uint64_t f11 = e[1U];
uint64_t f12 = e[2U];
uint64_t f13 = e[3U];
uint64_t f14 = e[4U];
uint64_t a0 = acc[0U];
uint64_t a1 = acc[1U];
uint64_t a2 = acc[2U];
uint64_t a3 = acc[3U];
uint64_t a4 = acc[4U];
uint64_t a01 = a0 + f10;
uint64_t a11 = a1 + f11;
uint64_t a21 = a2 + f12;
uint64_t a31 = a3 + f13;
uint64_t a41 = a4 + f14;
uint64_t a02 = r0 * a01;
uint64_t a12 = r1 * a01;
uint64_t a22 = r2 * a01;
uint64_t a32 = r3 * a01;
uint64_t a42 = r4 * a01;
uint64_t a03 = a02 + r54 * a11;
uint64_t a13 = a12 + r0 * a11;
uint64_t a23 = a22 + r1 * a11;
uint64_t a33 = a32 + r2 * a11;
uint64_t a43 = a42 + r3 * a11;
uint64_t a04 = a03 + r53 * a21;
uint64_t a14 = a13 + r54 * a21;
uint64_t a24 = a23 + r0 * a21;
uint64_t a34 = a33 + r1 * a21;
uint64_t a44 = a43 + r2 * a21;
uint64_t a05 = a04 + r52 * a31;
uint64_t a15 = a14 + r53 * a31;
uint64_t a25 = a24 + r54 * a31;
uint64_t a35 = a34 + r0 * a31;
uint64_t a45 = a44 + r1 * a31;
uint64_t a06 = a05 + r51 * a41;
uint64_t a16 = a15 + r52 * a41;
uint64_t a26 = a25 + r53 * a41;
uint64_t a36 = a35 + r54 * a41;
uint64_t a46 = a45 + r0 * a41;
uint64_t t0 = a06;
uint64_t t1 = a16;
uint64_t t2 = a26;
uint64_t t3 = a36;
uint64_t t4 = a46;
uint64_t mask26 = (uint64_t)0x3ffffffU;
uint64_t z0 = t0 >> (uint32_t)26U;
uint64_t z1 = t3 >> (uint32_t)26U;
uint64_t x0 = t0 & mask26;
uint64_t x3 = t3 & mask26;
uint64_t x1 = t1 + z0;
uint64_t x4 = t4 + z1;
uint64_t z01 = x1 >> (uint32_t)26U;
uint64_t z11 = x4 >> (uint32_t)26U;
uint64_t t = z11 << (uint32_t)2U;
uint64_t z12 = z11 + t;
uint64_t x11 = x1 & mask26;
uint64_t x41 = x4 & mask26;
uint64_t x2 = t2 + z01;
uint64_t x01 = x0 + z12;
uint64_t z02 = x2 >> (uint32_t)26U;
uint64_t z13 = x01 >> (uint32_t)26U;
uint64_t x21 = x2 & mask26;
uint64_t x02 = x01 & mask26;
uint64_t x31 = x3 + z02;
uint64_t x12 = x11 + z13;
uint64_t z03 = x31 >> (uint32_t)26U;
uint64_t x32 = x31 & mask26;
uint64_t x42 = x41 + z03;
uint64_t o0 = x02;
uint64_t o1 = x12;
uint64_t o2 = x21;
uint64_t o3 = x32;
uint64_t o4 = x42;
acc[0U] = o0;
acc[1U] = o1;
acc[2U] = o2;
acc[3U] = o3;
acc[4U] = o4;
Hacl_Poly1305_32_poly1305_finish(out, k, ctx);
}
void
Chacha20Poly1305_vsx_aead_encrypt(
uint8_t *k,
uint8_t *n,
uint32_t aadlen,
uint8_t *aad,
uint32_t mlen,
uint8_t *m,
uint8_t *cipher,
uint8_t *mac)
{
chacha20vsx(mlen, cipher, m, k, n, (uint32_t)1U);
uint8_t tmp[64U] = { 0U };
chacha20vsx((uint32_t)64U, tmp, tmp, k, n, (uint32_t)0U);
uint8_t *key = tmp;
poly1305_do_32(key, aadlen, aad, mlen, cipher, mac);
}
uint32_t
Chacha20Poly1305_vsx_aead_decrypt(
uint8_t *k,
uint8_t *n,
uint32_t aadlen,
uint8_t *aad,
uint32_t mlen,
uint8_t *m,
uint8_t *cipher,
uint8_t *mac)
{
uint8_t computed_mac[16U] = { 0U };
uint8_t tmp[64U] = { 0U };
chacha20vsx((uint32_t)64U, tmp, tmp, k, n, (uint32_t)0U);
uint8_t *key = tmp;
poly1305_do_32(key, aadlen, aad, mlen, cipher, computed_mac);
uint8_t res = (uint8_t)255U;
for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i++) {
uint8_t uu____0 = FStar_UInt8_eq_mask(computed_mac[i], mac[i]);
res = uu____0 & res;
}
uint8_t z = res;
if (z == (uint8_t)255U) {
chacha20vsx(mlen, m, cipher, k, n, (uint32_t)1U);
return (uint32_t)0U;
}
return (uint32_t)1U;
}

View file

@ -13,91 +13,135 @@
#include "secerr.h"
#include "blapit.h"
#include "blapii.h"
#ifndef NSS_DISABLE_CHACHAPOLY
#include "chacha20poly1305.h"
// Forward declaration from "Hacl_Chacha20_Vec128.h".
extern void Hacl_Chacha20_Vec128_chacha20(uint8_t *output, uint8_t *plain,
uint32_t len, uint8_t *k, uint8_t *n1,
uint32_t ctr);
// Forward declaration from "Hacl_Chacha20.h".
extern void Hacl_Chacha20_chacha20(uint8_t *output, uint8_t *plain, uint32_t len,
uint8_t *k, uint8_t *n1, uint32_t ctr);
#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__))
/* Use HACL* Poly1305 on 64-bit Intel and ARM */
#include "verified/Hacl_Poly1305_64.h"
#define NSS_POLY1305_64 1
#define Hacl_Poly1305_update Hacl_Poly1305_64_update
#define Hacl_Poly1305_mk_state Hacl_Poly1305_64_mk_state
#define Hacl_Poly1305_init Hacl_Poly1305_64_init
#define Hacl_Poly1305_finish Hacl_Poly1305_64_finish
typedef Hacl_Impl_Poly1305_64_State_poly1305_state Hacl_Impl_Poly1305_State_poly1305_state;
#else
/* All other platforms get the 32-bit poly1305 HACL* implementation. */
#include "verified/Hacl_Poly1305_32.h"
#define NSS_POLY1305_32 1
#define Hacl_Poly1305_update Hacl_Poly1305_32_update
#define Hacl_Poly1305_mk_state Hacl_Poly1305_32_mk_state
#define Hacl_Poly1305_init Hacl_Poly1305_32_init
#define Hacl_Poly1305_finish Hacl_Poly1305_32_finish
typedef Hacl_Impl_Poly1305_32_State_poly1305_state Hacl_Impl_Poly1305_State_poly1305_state;
#endif /* HAVE_INT128_SUPPORT */
// There are three implementations of ChaCha20Poly1305:
// 1) 128-bit with AVX hardware acceleration used on x64
// 2) 256-bit with AVX2 hardware acceleration used on x64
// 3) 32-bit used on all other platforms
static void
Poly1305PadUpdate(Hacl_Impl_Poly1305_State_poly1305_state state,
unsigned char *block, const unsigned char *p,
const unsigned int pLen)
// On x64 when AVX2 and other necessary registers are available,
// the 256bit-verctorized version will be used. When AVX2 features
// are unavailable or disabled but AVX registers are available, the
// 128bit-vectorized version will be used. In all other cases the
// scalar version of the HACL* code will be used.
// Instead of including the headers (they bring other things we don't want),
// we declare the functions here.
// Usage is guarded by runtime checks of required hardware features.
// Forward declaration from Hacl_Chacha20_Vec128.h and Hacl_Chacha20Poly1305_128.h.
extern void Hacl_Chacha20_Vec128_chacha20_encrypt_128(uint32_t len, uint8_t *out,
uint8_t *text, uint8_t *key,
uint8_t *n1, uint32_t ctr);
extern void
Hacl_Chacha20Poly1305_128_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
extern uint32_t
Hacl_Chacha20Poly1305_128_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
// Forward declaration from Hacl_Chacha20_Vec256.h and Hacl_Chacha20Poly1305_256.h.
extern void Hacl_Chacha20_Vec256_chacha20_encrypt_256(uint32_t len, uint8_t *out,
uint8_t *text, uint8_t *key,
uint8_t *n1, uint32_t ctr);
extern void
Hacl_Chacha20Poly1305_256_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
extern uint32_t
Hacl_Chacha20Poly1305_256_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
// Forward declaration from Hacl_Chacha20.h and Hacl_Chacha20Poly1305_32.h.
extern void Hacl_Chacha20_chacha20_encrypt(uint32_t len, uint8_t *out,
uint8_t *text, uint8_t *key,
uint8_t *n1, uint32_t ctr);
extern void
Hacl_Chacha20Poly1305_32_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
extern uint32_t
Hacl_Chacha20Poly1305_32_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
// Forward declaration from chacha20-ppc64le.S
void chacha20vsx(uint32_t len, uint8_t *output, uint8_t *block, uint8_t *k,
uint8_t *nonce, uint32_t ctr);
// Forward declaration from chacha20poly1305-ppc.c
extern void
Chacha20Poly1305_vsx_aead_encrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
extern uint32_t
Chacha20Poly1305_vsx_aead_decrypt(uint8_t *k, uint8_t *n1, uint32_t aadlen,
uint8_t *aad, uint32_t mlen, uint8_t *m,
uint8_t *cipher, uint8_t *mac);
SECStatus
ChaCha20_InitContext(ChaCha20Context *ctx, const unsigned char *key,
unsigned int keyLen, const unsigned char *nonce,
unsigned int nonceLen, PRUint32 ctr)
{
unsigned int pRemLen = pLen % 16;
Hacl_Poly1305_update(state, (uint8_t *)p, (pLen / 16));
if (pRemLen > 0) {
memcpy(block, p + (pLen - pRemLen), pRemLen);
Hacl_Poly1305_update(state, block, 1);
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
if (keyLen != 32) {
PORT_SetError(SEC_ERROR_BAD_KEY);
return SECFailure;
}
if (nonceLen != 12) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
}
/* Poly1305Do writes the Poly1305 authenticator of the given additional data
* and ciphertext to |out|. */
static void
Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen,
const unsigned char *ciphertext, unsigned int ciphertextLen,
const unsigned char key[32])
{
#ifdef NSS_POLY1305_64
uint64_t stateStack[6U] = { 0U };
size_t offset = 3;
#elif defined NSS_POLY1305_32
uint32_t stateStack[10U] = { 0U };
size_t offset = 5;
#else
#error "This can't happen."
ctx->counter = ctr;
PORT_Memcpy(ctx->key, key, sizeof(ctx->key));
PORT_Memcpy(ctx->nonce, nonce, sizeof(ctx->nonce));
return SECSuccess;
#endif
}
ChaCha20Context *
ChaCha20_CreateContext(const unsigned char *key, unsigned int keyLen,
const unsigned char *nonce, unsigned int nonceLen,
PRUint32 ctr)
{
#ifdef NSS_DISABLE_CHACHAPOLY
return NULL;
#else
ChaCha20Context *ctx;
ctx = PORT_New(ChaCha20Context);
if (ctx == NULL) {
return NULL;
}
if (ChaCha20_InitContext(ctx, key, keyLen, nonce, nonceLen, ctr) != SECSuccess) {
PORT_Free(ctx);
ctx = NULL;
}
return ctx;
#endif
}
void
ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit)
{
#ifndef NSS_DISABLE_CHACHAPOLY
PORT_Memset(ctx, 0, sizeof(*ctx));
if (freeit) {
PORT_Free(ctx);
}
#endif
Hacl_Impl_Poly1305_State_poly1305_state state =
Hacl_Poly1305_mk_state(stateStack, stateStack + offset);
unsigned char block[16] = { 0 };
Hacl_Poly1305_init(state, (uint8_t *)key);
Poly1305PadUpdate(state, block, ad, adLen);
memset(block, 0, 16);
Poly1305PadUpdate(state, block, ciphertext, ciphertextLen);
unsigned int i;
unsigned int j;
for (i = 0, j = adLen; i < 8; i++, j >>= 8) {
block[i] = j;
}
for (i = 8, j = ciphertextLen; i < 16; i++, j >>= 8) {
block[i] = j;
}
Hacl_Poly1305_update(state, block, 1);
Hacl_Poly1305_finish(state, out, (uint8_t *)(key + 16));
#undef NSS_POLY1305_64
#undef NSS_POLY1305_32
}
#endif /* NSS_DISABLE_CHACHAPOLY */
SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
@ -162,10 +206,31 @@ void
ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k,
uint8_t *nonce, uint32_t ctr)
{
if (ssse3_support() || arm_neon_support()) {
Hacl_Chacha20_Vec128_chacha20(output, block, len, k, nonce, ctr);
} else {
Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr);
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
Hacl_Chacha20_Vec256_chacha20_encrypt_256(len, output, block, k, nonce, ctr);
return;
}
#endif
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
Hacl_Chacha20_Vec128_chacha20_encrypt_128(len, output, block, k, nonce, ctr);
return;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
chacha20vsx(len, output, block, k, nonce, ctr);
return;
}
#endif
{
Hacl_Chacha20_chacha20_encrypt(len, output, block, k, nonce, ctr);
return;
}
}
#endif /* NSS_DISABLE_CHACHAPOLY */
@ -178,9 +243,12 @@ ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len
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;
if (sizeof(len) > 4) {
unsigned long long len_ull = len;
if (len_ull >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
ChaCha20Xor(output, (uint8_t *)block, len, (uint8_t *)k,
(uint8_t *)nonce, ctr);
@ -198,34 +266,60 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output,
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
unsigned char block[64];
unsigned char tag[16];
if (nonceLen != 12) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
// 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 (sizeof(inputLen) > 4) {
unsigned long long inputLen_ull = inputLen;
if (inputLen_ull >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
if (maxOutputLen < inputLen + ctx->tagLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
PORT_Memset(block, 0, sizeof(block));
// Generate a block of keystream. The first 32 bytes will be the poly1305
// key. The remainder of the block is discarded.
ChaCha20Xor(block, (uint8_t *)block, sizeof(block), (uint8_t *)ctx->key,
(uint8_t *)nonce, 0);
ChaCha20Xor(output, (uint8_t *)input, inputLen, (uint8_t *)ctx->key,
(uint8_t *)nonce, 1);
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
Hacl_Chacha20Poly1305_256_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, output + inputLen);
goto finish;
}
#endif
Poly1305Do(tag, ad, adLen, output, inputLen, block);
PORT_Memcpy(output + inputLen, tag, ctx->tagLen);
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
Hacl_Chacha20Poly1305_128_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, output + inputLen);
goto finish;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
Chacha20Poly1305_vsx_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, output + inputLen);
goto finish;
}
#endif
{
Hacl_Chacha20Poly1305_32_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, output + inputLen);
goto finish;
}
finish:
*outputLen = inputLen + ctx->tagLen;
return SECSuccess;
#endif
@ -241,8 +335,6 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
unsigned char block[64];
unsigned char tag[16];
unsigned int ciphertextLen;
if (nonceLen != 12) {
@ -264,20 +356,195 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output,
return SECFailure;
}
PORT_Memset(block, 0, sizeof(block));
// Generate a block of keystream. The first 32 bytes will be the poly1305
// key. The remainder of the block is discarded.
ChaCha20Xor(block, (uint8_t *)block, sizeof(block), (uint8_t *)ctx->key,
(uint8_t *)nonce, 0);
Poly1305Do(tag, ad, adLen, input, ciphertextLen, block);
if (NSS_SecureMemcmp(tag, &input[ciphertextLen], ctx->tagLen) != 0) {
uint32_t res = 1;
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
res = Hacl_Chacha20Poly1305_256_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen);
goto finish;
}
#endif
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
res = Hacl_Chacha20Poly1305_128_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen);
goto finish;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
res = Chacha20Poly1305_vsx_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen);
goto finish;
}
#endif
{
res = Hacl_Chacha20Poly1305_32_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)input + ciphertextLen);
goto finish;
}
finish:
if (res) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
*outputLen = ciphertextLen;
return SECSuccess;
#endif
}
SECStatus
ChaCha20Poly1305_Encrypt(const ChaCha20Poly1305Context *ctx,
unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen, const unsigned char *nonce,
unsigned int nonceLen, const unsigned char *ad,
unsigned int adLen, unsigned char *outTag)
{
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
if (nonceLen != 12) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(inputLen) > 4) {
unsigned long long inputLen_ull = inputLen;
if (inputLen_ull >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
Hacl_Chacha20Poly1305_256_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
}
#endif
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
Hacl_Chacha20Poly1305_128_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
Chacha20Poly1305_vsx_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
}
#endif
{
Hacl_Chacha20Poly1305_32_aead_encrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, inputLen,
(uint8_t *)input, output, outTag);
goto finish;
}
finish:
*outputLen = inputLen;
return SECSuccess;
#endif
}
SECStatus
ChaCha20Poly1305_Decrypt(const ChaCha20Poly1305Context *ctx,
unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen, const unsigned char *nonce,
unsigned int nonceLen, const unsigned char *ad,
unsigned int adLen, const unsigned char *tagIn)
{
#ifdef NSS_DISABLE_CHACHAPOLY
return SECFailure;
#else
unsigned int ciphertextLen;
if (nonceLen != 12) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
ciphertextLen = inputLen;
if (maxOutputLen < ciphertextLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
// ChaCha has a 64 octet block, with a 32-bit block counter.
if (sizeof(inputLen) > 4) {
unsigned long long inputLen_ull = inputLen;
if (inputLen_ull >= (1ULL << (6 + 32))) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
uint32_t res = 1;
#ifdef NSS_X64
#ifndef NSS_DISABLE_AVX2
if (avx2_support()) {
res = Hacl_Chacha20Poly1305_256_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn);
goto finish;
}
#endif
#ifndef NSS_DISABLE_SSE3
if (ssse3_support() && sse4_1_support() && avx_support()) {
res = Hacl_Chacha20Poly1305_128_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn);
goto finish;
}
#endif
#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) && \
!defined(NSS_DISABLE_ALTIVEC) && !defined(NSS_DISABLE_CRYPTO_VSX)
if (ppc_crypto_support()) {
res = Chacha20Poly1305_vsx_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn);
goto finish;
}
#endif
{
res = Hacl_Chacha20Poly1305_32_aead_decrypt(
(uint8_t *)ctx->key, (uint8_t *)nonce, adLen, (uint8_t *)ad, ciphertextLen,
(uint8_t *)output, (uint8_t *)input, (uint8_t *)tagIn);
goto finish;
}
finish:
if (res) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
ChaCha20Xor(output, (uint8_t *)input, ciphertextLen, (uint8_t *)ctx->key,
(uint8_t *)nonce, 1);
*outputLen = ciphertextLen;
return SECSuccess;
#endif

View file

@ -12,4 +12,10 @@ struct ChaCha20Poly1305ContextStr {
unsigned char tagLen;
};
struct ChaCha20ContextStr {
unsigned char key[32];
unsigned char nonce[12];
PRUint32 counter;
};
#endif /* _CHACHA20_POLY1305_H_ */

View file

@ -24,7 +24,7 @@ struct CMACContextStr {
union {
AESContext *aes;
} cipher;
int blockSize;
unsigned int blockSize;
/* Internal keys which are conditionally used by the algorithm. Derived
* from encrypting the NULL block. We leave the storing of (and the
@ -210,7 +210,7 @@ SECStatus
CMAC_Update(CMACContext *ctx, const unsigned char *data,
unsigned int data_len)
{
int data_index = 0;
unsigned int data_index = 0;
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;

View file

@ -47,10 +47,6 @@ endif
ifeq (,$(filter-out WIN%,$(OS_TARGET)))
# don't want the 32 in the shared library name
SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX)
RES = $(OBJDIR)/$(LIBRARY_NAME).res
RESNAME = freebl.rc
ifdef NS_USE_GCC

View file

@ -13,7 +13,9 @@
#include "secerr.h"
#ifdef USE_HW_AES
#ifdef NSS_X86_OR_X64
#include "intel-aes.h"
#endif
#include "rijndael.h"
#endif
@ -207,7 +209,7 @@ CTR_Update(CTRContext *ctr, unsigned char *outbuf,
return SECSuccess;
}
#if defined(USE_HW_AES) && defined(_MSC_VER)
#if defined(USE_HW_AES) && defined(_MSC_VER) && defined(NSS_X86_OR_X64)
SECStatus
CTR_Update_HW_AES(CTRContext *ctr, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,

View file

@ -6,11 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#include "../stubs.h"
#endif
#include "blapi.h"
#include "blapii.h"
#include "../blapi.h"
#include "../blapii.h"
#include "secerr.h"
#ifdef XP_UNIX_XXX
#include <stddef.h> /* for ptrdiff_t */

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#include "../stubs.h"
#endif
#include <stdio.h>
@ -416,12 +416,23 @@ SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE],
void
SEED_ecb_encrypt(const unsigned char *in,
unsigned char *out,
size_t inLen,
const SEED_KEY_SCHEDULE *ks, int enc)
{
if (enc) {
SEED_encrypt(in, out, ks);
while (inLen > 0) {
SEED_encrypt(in, out, ks);
out += SEED_BLOCK_SIZE;
in += SEED_BLOCK_SIZE;
inLen -= SEED_BLOCK_SIZE;
}
} else {
SEED_decrypt(in, out, ks);
while (inLen > 0) {
SEED_decrypt(in, out, ks);
out += SEED_BLOCK_SIZE;
in += SEED_BLOCK_SIZE;
inLen -= SEED_BLOCK_SIZE;
}
}
}
@ -602,7 +613,7 @@ SEED_Encrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
switch (cx->mode) {
case NSS_SEED:
SEED_ecb_encrypt(in, out, &cx->ks, 1);
SEED_ecb_encrypt(in, out, inLen, &cx->ks, 1);
*outLen = inLen;
break;
@ -642,7 +653,7 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
switch (cx->mode) {
case NSS_SEED:
SEED_ecb_encrypt(in, out, &cx->ks, 0);
SEED_ecb_encrypt(in, out, inLen, &cx->ks, 0);
*outLen = inLen;
break;

View file

@ -113,7 +113,7 @@ void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE],
const SEED_KEY_SCHEDULE *ks);
void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out,
const SEED_KEY_SCHEDULE *ks, int enc);
size_t inLen, const SEED_KEY_SCHEDULE *ks, int enc);
void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SEED_KEY_SCHEDULE *ks,
unsigned char ivec[SEED_BLOCK_SIZE], int enc);

View file

@ -99,7 +99,8 @@ RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
memset(dest, 0, len);
memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE));
Hacl_Chacha20_chacha20(dest, (uint8_t *)dest, len, (uint8_t *)key, nonce, 0);
Hacl_Chacha20_chacha20_encrypt(len, (uint8_t *)dest, (uint8_t *)dest,
(uint8_t *)key, nonce, 0);
ChaCha20Poly1305_DestroyContext(cx, PR_TRUE);
PZ_Unlock(rng_lock);
@ -154,7 +155,9 @@ PRNGTEST_RunHealthTests()
}
SECStatus
PRNGTEST_Instantiate_Kat()
PRNGTEST_Instantiate_Kat(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len)
{
return SECFailure;
}

View file

@ -78,7 +78,7 @@ DH_GenParam(int primeLen, DHParams **params)
CHECK_MPI_OK(mp_init(&h));
CHECK_MPI_OK(mp_init(&psub1));
CHECK_MPI_OK(mp_init(&test));
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
/* generate prime with MPI, uses Miller-Rabin to generate safe prime. */
CHECK_SEC_OK(generate_prime(&p, primeLen));
/* construct Sophie-Germain prime q = (p-1)/2. */
CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1));
@ -257,17 +257,17 @@ DH_Derive(SECItem *publicValue,
}
/*
* We check to make sure that ZZ is not equal to 1 or -1 mod p.
* We check to make sure that ZZ is not equal to 0, 1 or -1 mod p.
* This helps guard against small subgroup attacks, since an attacker
* using a subgroup of size N will produce 1 or -1 with probability 1/N.
* using a subgroup of size N will produce 0, 1 or -1 with probability 1/N.
* When the protocol is executed within a properly large subgroup, the
* probability of this result will be negligibly small. For example,
* with a strong prime of the form 2p+1, the probability will be 1/p.
* with a safe prime of the form 2q+1, the probability will be 1/q.
*
* We return MP_BADARG because this is probably the result of a bad
* public value or a bad prime having been provided.
*/
if (mp_cmp_d(&ZZ, 1) == 0 ||
if (mp_cmp_d(&ZZ, 0) == 0 || mp_cmp_d(&ZZ, 1) == 0 ||
mp_cmp(&ZZ, &psub1) == 0) {
err = MP_BADARG;
goto cleanup;
@ -413,6 +413,35 @@ cleanup:
return SECSuccess;
}
/* Test counts based on the fact the prime and subprime
* were given to us */
static int
dh_prime_testcount(int prime_length)
{
if (prime_length < 1024) {
return 50;
} else if (prime_length < 2048) {
return 40;
} else if (prime_length < 3072) {
return 56;
}
return 64;
}
PRBool
KEA_PrimeCheck(SECItem *prime)
{
mp_int p;
mp_err err = 0;
MP_DIGITS(&p) = 0;
CHECK_MPI_OK(mp_init(&p));
SECITEM_TO_MPINT(*prime, &p);
CHECK_MPI_OK(mpp_pprime_secure(&p, dh_prime_testcount(prime->len)));
cleanup:
mp_clear(&p);
return err ? PR_FALSE : PR_TRUE;
}
PRBool
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
{

View file

@ -145,6 +145,7 @@ prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
requested_bytes += hash_return_len;
no_of_bytes_to_return -= hash_return_len;
}
SHA256_DestroyContext(&ctx, PR_FALSE);
return SECSuccess;
}
@ -197,6 +198,7 @@ prng_initEntropy(void)
SHA256_End(&ctx, globalrng->previousEntropyHash, NULL,
sizeof(globalrng->previousEntropyHash));
PORT_Memset(block, 0, sizeof(block));
SHA256_DestroyContext(&ctx, PR_FALSE);
return PR_SUCCESS;
}
@ -244,6 +246,7 @@ prng_getEntropy(PRUint8 *buffer, size_t requestLength)
}
out:
PORT_Memset(hash, 0, sizeof hash);
PORT_Memset(block, 0, sizeof block);
return rv;
}
@ -388,6 +391,7 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
* This increments data if no_of_returned_bytes is not zero */
carry = no_of_returned_bytes;
PRNG_ADD_CARRY_ONLY(data, (sizeof data) - 1, carry);
SHA256_DestroyContext(&ctx, PR_FALSE);
}
PORT_Memset(data, 0, sizeof data);
PORT_Memset(thisHash, 0, sizeof thisHash);
@ -430,6 +434,7 @@ prng_generateNewBytes(RNGContext *rng,
SHA256_End(&ctx, w, NULL, sizeof w);
PRNG_ADD_BITS_AND_CARRY(V(rng), VSize(rng), w, sizeof w, carry)
PORT_Memset(w, 0, sizeof w);
SHA256_DestroyContext(&ctx, PR_FALSE);
#undef w
}
@ -450,6 +455,7 @@ prng_generateNewBytes(RNGContext *rng,
PRNG_ADD_CARRY_ONLY(rng->reseed_counter, (sizeof rng->reseed_counter) - 1, carry);
/* if the prng failed, don't return any output, signal softoken */
PORT_Memset(H, 0, sizeof H);
if (!rng->isValid) {
PORT_Memset(returned_bytes, 0, no_of_returned_bytes);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);

View file

@ -260,7 +260,7 @@ DSA_NewRandom(PLArenaPool *arena, const SECItem *q, SECItem *seed)
PORT_SetError(SEC_ERROR_NEED_RANDOM);
loser:
if (arena != NULL) {
SECITEM_FreeItem(seed, PR_FALSE);
SECITEM_ZfreeItem(seed, PR_FALSE);
}
return SECFailure;
}
@ -295,7 +295,7 @@ DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
rv = dsa_NewKeyExtended(params, &seed, privKey);
}
}
SECITEM_FreeItem(&seed, PR_FALSE);
SECITEM_ZfreeItem(&seed, PR_FALSE);
return rv;
}
@ -403,6 +403,8 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
CHECK_MPI_OK(mp_exptmod(&g, &t, &p, &r)); /* r = g**t mod p */
/* r is now g**(k+q*fuzz) == g**k mod p */
CHECK_MPI_OK(mp_mod(&r, &q, &r)); /* r = r mod q */
/* make sure fuzz is cleared off the stack and not optimized away */
*(volatile mp_digit *)&fuzz = 0;
/*
** FIPS 186-1, Section 5, Step 2
@ -415,14 +417,14 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
goto cleanup;
}
SECITEM_TO_MPINT(t2, &t); /* t <-$ Zq */
SECITEM_FreeItem(&t2, PR_FALSE);
SECITEM_ZfreeItem(&t2, PR_FALSE);
if (DSA_NewRandom(NULL, &key->params.subPrime, &t2) != SECSuccess) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
rv = SECFailure;
goto cleanup;
}
SECITEM_TO_MPINT(t2, &ar); /* ar <-$ Zq */
SECITEM_FreeItem(&t2, PR_FALSE);
SECITEM_ZfreeItem(&t2, PR_FALSE);
/* Using mp_invmod on k directly would leak bits from k. */
CHECK_MPI_OK(mp_mul(&k, &ar, &k)); /* k = k * ar */
@ -530,6 +532,7 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
rv = dsa_SignDigest(key, signature, digest, kSeed);
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
--retries > 0);
PORT_Memset(kSeed, 0, sizeof kSeed);
return rv;
}
@ -670,6 +673,7 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
verified = SECSuccess; /* Signature verified. */
}
cleanup:
PORT_Memset(localDigestData, 0, sizeof localDigestData);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);

View file

@ -7,6 +7,7 @@
#endif
#include "blapi.h"
#include "blapii.h"
#include "prerr.h"
#include "secerr.h"
#include "secmpi.h"
@ -15,6 +16,8 @@
#include "ec.h"
#include "ecl.h"
#define EC_DOUBLECHECK PR_FALSE
static const ECMethod kMethods[] = {
{ ECCurve25519,
ec_Curve25519_pt_mul,
@ -62,7 +65,7 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
ECGroup *group = NULL;
SECStatus rv = SECFailure;
mp_err err = MP_OKAY;
int len;
unsigned int len;
#if EC_DEBUG
int i;
@ -96,7 +99,7 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
#endif
/* NOTE: We only support uncompressed points for now */
len = (params->fieldID.size + 7) >> 3;
len = (((unsigned int)params->fieldID.size) + 7) >> 3;
if (pointP != NULL) {
if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
(pointP->len != (2 * len + 1))) {
@ -146,6 +149,10 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
CHECK_MPI_OK(ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy));
}
/* our ECC codes uses large stack variables to store intermediate results,
* clear our stack before returning to prevent CSP leakage */
BLAPI_CLEAR_STACK(2048)
/* Construct the SECItem representation of point Q */
pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
CHECK_MPI_OK(mp_to_fixlen_octets(&Qx, pointQ->data + 1,
@ -428,7 +435,7 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
ECGroup *group = NULL;
SECStatus rv = SECFailure;
mp_err err = MP_OKAY;
int len;
unsigned int len;
if (!ecParams || ecParams->name == ECCurve_noName ||
!publicValue || !publicValue->len) {
@ -448,7 +455,7 @@ EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue)
}
/* NOTE: We only support uncompressed points for now */
len = (ecParams->fieldID.size + 7) >> 3;
len = (((unsigned int)ecParams->fieldID.size) + 7) >> 3;
if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
return SECFailure;
@ -531,7 +538,6 @@ ECDH_Derive(SECItem *publicValue,
unsigned int len = 0;
SECItem pointQ = { siBuffer, NULL, 0 };
mp_int k; /* to hold the private value */
mp_int cofactor;
mp_err err = MP_OKAY;
#if EC_DEBUG
int i;
@ -596,11 +602,13 @@ ECDH_Derive(SECItem *publicValue,
(mp_size)privateValue->len));
if (withCofactor && (ecParams->cofactor != 1)) {
mp_int cofactor;
/* multiply k with the cofactor */
MP_DIGITS(&cofactor) = 0;
CHECK_MPI_OK(mp_init(&cofactor));
mp_set(&cofactor, ecParams->cofactor);
CHECK_MPI_OK(mp_mul(&k, &cofactor, &k));
mp_clear(&cofactor);
}
/* Multiply our private key and peer's public point */
@ -645,9 +653,10 @@ cleanup:
* on the digest using the given key and the random value kb (used in
* computing s).
*/
SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb, const int kblen)
static SECStatus
ec_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb, const int kblen)
{
SECStatus rv = SECFailure;
mp_int x1;
@ -858,7 +867,7 @@ cleanup:
mp_clear(&ar);
if (t2) {
PORT_Free(t2);
PORT_ZFree(t2, 2 * ecParams->order.len);
}
if (kGpoint.data) {
@ -878,6 +887,34 @@ cleanup:
return rv;
}
SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
const SECItem *digest, const unsigned char *kb, const int kblen)
{
#if EC_DEBUG || EC_DOUBLECHECK
SECItem *signature2 = SECITEM_AllocItem(NULL, NULL, signature->len);
SECStatus signSuccess = ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
SECStatus signSuccessDouble = ec_SignDigestWithSeed(key, signature2, digest, kb, kblen);
int signaturesEqual = NSS_SecureMemcmp(signature, signature2, signature->len);
SECStatus rv;
if ((signaturesEqual == 0) && (signSuccess == SECSuccess) && (signSuccessDouble == SECSuccess)) {
rv = SECSuccess;
} else {
rv = SECFailure;
}
#if EC_DEBUG
printf("ECDSA signing with seed %s after signing twice\n", (rv == SECSuccess) ? "succeeded" : "failed");
#endif
SECITEM_FreeItem(signature2, PR_TRUE);
return rv;
#else
return ec_SignDigestWithSeed(key, signature, digest, kb, kblen);
#endif
}
/*
** Computes the ECDSA signature on the digest using the given key
** and a random seed.

View file

@ -3,12 +3,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecl-priv.h"
#include "../verified/Hacl_Curve25519.h"
#if HACL_CAN_COMPILE_INLINE_ASM
#include "../verified/Hacl_Curve25519_64.h"
#else
#include "../verified/Hacl_Curve25519_51.h"
#endif
SECStatus
ec_Curve25519_mul(uint8_t *mypublic, const uint8_t *secret, const uint8_t *basepoint)
{
// Note: this cast is safe because HaCl* state has a post-condition that only "mypublic" changed.
Hacl_Curve25519_crypto_scalarmult(mypublic, (uint8_t *)secret, (uint8_t *)basepoint);
// Note: this cast is safe because HaCl* state has a post-condition that only "mypublic" changed.
#if defined HACL_CAN_COMPILE_INLINE_ASM
Hacl_Curve25519_64_ecdh(mypublic, (uint8_t *)secret, (uint8_t *)basepoint);
#else
Hacl_Curve25519_51_ecdh(mypublic, (uint8_t *)secret, (uint8_t *)basepoint);
#endif
return 0;
}

View file

@ -13,38 +13,31 @@
#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
static const PRUint8 irr256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b256[32] =
{ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
static const PRUint8 x256[32] =
{ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
static const PRUint8 y256[32] =
{ 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const PRUint8 order256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
static const PRUint8 base256[66] =
{ 0x04, 0x00,
0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const PRUint8 irr256[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a256[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b256[32] = { 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
static const PRUint8 x256[32] = { 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
static const PRUint8 y256[32] = { 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const PRUint8 order256[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
static const PRUint8 base256[66] = { 0x04, 0x00,
0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const ECCurveBytes ecCurve_NIST_P256 = {
"NIST-P256", ECField_GFp, 256,
@ -53,46 +46,39 @@ static const ECCurveBytes ecCurve_NIST_P256 = {
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const PRUint8 irr384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b384[48] =
{ 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
static const PRUint8 x384[48] =
{ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
static const PRUint8 y384[48] =
{ 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const PRUint8 order384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
static const PRUint8 base384[98] =
{ 0x04, 0x00,
0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const PRUint8 irr384[48] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a384[48] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b384[48] = { 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
static const PRUint8 x384[48] = { 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
static const PRUint8 y384[48] = { 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const PRUint8 order384[48] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
static const PRUint8 base384[98] = { 0x04, 0x00,
0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const ECCurveBytes ecCurve_NIST_P384 = {
"NIST-P384", ECField_GFp, 384,
@ -101,64 +87,57 @@ static const ECCurveBytes ecCurve_NIST_P384 = {
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const PRUint8 irr521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b521[66] =
{ 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
static const PRUint8 x521[66] =
{ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
static const PRUint8 y521[66] =
{ 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
static const PRUint8 order521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
static const PRUint8 base521[134] =
{
0x04, 0x00,
0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
};
static const PRUint8 irr521[66] = { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a521[66] = { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b521[66] = { 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
static const PRUint8 x521[66] = { 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
static const PRUint8 y521[66] = { 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
static const PRUint8 order521[66] = { 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
static const PRUint8 base521[134] = {
0x04, 0x00,
0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
};
static const ECCurveBytes ecCurve_NIST_P521 = {
"NIST-P521", ECField_GFp, 521,
@ -167,37 +146,30 @@ static const ECCurveBytes ecCurve_NIST_P521 = {
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const PRUint8 irr25519[32] =
{ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
static const PRUint8 a25519[32] =
{ 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 b25519[32] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 x25519[32] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
static const PRUint8 y25519[32] =
{ 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
static const PRUint8 order25519[32] =
{ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
static const PRUint8 base25519[66] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
static const PRUint8 irr25519[32] = { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
static const PRUint8 a25519[32] = { 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 b25519[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 x25519[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
static const PRUint8 y25519[32] = { 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
static const PRUint8 order25519[32] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
static const PRUint8 base25519[66] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
static const ECCurveBytes ecCurve_25519 = {
"Curve25519", ECField_GFp, 255,

View file

@ -27,7 +27,7 @@ SECStatus
ec_Curve25519_pt_validate(const SECItem *px)
{
PRUint8 *p;
int i;
PRUint64 i;
PRUint8 forbiddenValues[12][32] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View file

@ -150,7 +150,7 @@ static const limb kPrecomputed[NLIMBS * 2 * 15 * 2] = {
0x87d43b7, 0x37ab11b, 0x19d292ce, 0xf8d4692, 0x18c3053f, 0x8863e13, 0x4c146c0, 0x6bdf55a, 0x4e4457d,
0x16152289, 0xac78ec2, 0x1a59c5a2, 0x2028b97, 0x71c2d01, 0x295851f, 0x404747b, 0x878558d, 0x7d29aa4,
0x13d8341f, 0x8daefd7, 0x139c972d, 0x6b7ea75, 0xd4a9dde, 0xff163d8, 0x81d55d7, 0xa5bef68, 0xb7b30d8,
0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78,
0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78
};
/* Field element operations:

View file

@ -196,7 +196,7 @@ ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
}
}
#else /* double and add/subtract method from \
* standard */
* standard */
/* k3 = 3 * k */
MP_CHECKOK(mp_set_int(&k3, 3));
MP_CHECKOK(mp_mul(&k, &k3, &k3));

View file

@ -192,7 +192,7 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
mp_int raz4;
mp_int scratch[MAX_SCRATCH];
signed char *naf = NULL;
int i, orderBitSize;
int i, orderBitSize = 0;
MP_DIGITS(&rz) = 0;
MP_DIGITS(&raz4) = 0;
@ -289,6 +289,9 @@ CLEANUP:
mp_clear(&tpy);
mp_clear(&rz);
mp_clear(&raz4);
if (naf) {
memset(naf, 0, orderBitSize + 1);
}
free(naf);
return res;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@
#include "prtypes.h"
#include "secitem.h"
#include "pkcs11t.h"
#include "cmac.h"
#include "ec.h" /* Required for EC */
@ -45,7 +46,8 @@ static void INIT_FUNCTION bl_startup_tests(void);
#if defined(XP_WIN) && !defined(NSS_NO_INIT_SUPPORT)
#include <windows.h>
BOOL WINAPI DllMain(
BOOL WINAPI
DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
@ -99,6 +101,7 @@ BOOL WINAPI DllMain(
#define FIPS_AES_BLOCK_SIZE 16 /* 128-bits */
#define FIPS_AES_ENCRYPT_LENGTH 16 /* 128-bits */
#define FIPS_AES_DECRYPT_LENGTH 16 /* 128-bits */
#define FIPS_AES_CMAC_LENGTH 16 /* 128-bits */
#define FIPS_AES_128_KEY_SIZE 16 /* 128-bits */
#define FIPS_AES_192_KEY_SIZE 24 /* 192-bits */
#define FIPS_AES_256_KEY_SIZE 32 /* 256-bits */
@ -280,12 +283,10 @@ static SECStatus
freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
{
/* AES Known Key (up to 256-bits). */
static const PRUint8 aes_known_key[] =
{ "AES-128 RIJNDAELLEADNJIR 821-SEA" };
static const PRUint8 aes_known_key[] = { "AES-128 RIJNDAELLEADNJIR 821-SEA" };
/* AES-CBC Known Initialization Vector (128-bits). */
static const PRUint8 aes_cbc_known_initialization_vector[] =
{ "SecurityytiruceS" };
static const PRUint8 aes_cbc_known_initialization_vector[] = { "SecurityytiruceS" };
/* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
@ -310,6 +311,11 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
};
static const PRUint8 aes_cmac128_known_ciphertext[] = {
0x54, 0x11, 0xe2, 0x57, 0xbd, 0x2a, 0xdf, 0x9d,
0x1a, 0x89, 0x72, 0x80, 0x84, 0x4c, 0x7e, 0x93
};
/* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
@ -328,6 +334,11 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
};
static const PRUint8 aes_cmac192_known_ciphertext[] = {
0x0e, 0x07, 0x99, 0x1e, 0xf6, 0xee, 0xfa, 0x2c,
0x1b, 0xfc, 0xce, 0x94, 0x92, 0x2d, 0xf1, 0xab
};
/* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
@ -346,6 +357,12 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
};
static const PRUint8 aes_cmac256_known_ciphertext[] = {
0xc1, 0x26, 0x69, 0x32, 0x51, 0x13, 0x65, 0xac,
0x71, 0x23, 0xe4, 0xe7, 0xb9, 0x0c, 0x88, 0x9f
};
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;
@ -355,13 +372,17 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
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;
const PRUint8 *aes_cmac_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cmac128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cmac192_known_ciphertext : aes_cmac256_known_ciphertext;
/* AES variables. */
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context;
CMACContext *cmac_context;
unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted;
CK_GCM_PARAMS gcmParams;
CK_NSS_GCM_PARAMS gcmParams;
SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */
@ -547,6 +568,44 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
return (SECFailure);
}
/******************************************************/
/* AES-CMAC Known Answer Encryption Test. */
/******************************************************/
cmac_context = CMAC_Create(CMAC_AES, aes_known_key, aes_key_size);
if (cmac_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = CMAC_Begin(cmac_context);
if (aes_status != SECSuccess) {
CMAC_Destroy(cmac_context, PR_TRUE);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
aes_status = CMAC_Update(cmac_context, aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH);
if (aes_status != SECSuccess) {
CMAC_Destroy(cmac_context, PR_TRUE);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
aes_status = CMAC_Finish(cmac_context, aes_computed_ciphertext,
&aes_bytes_encrypted, FIPS_AES_CMAC_LENGTH);
CMAC_Destroy(cmac_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_encrypted != FIPS_AES_CMAC_LENGTH) ||
(PORT_Memcmp(aes_computed_ciphertext, aes_cmac_known_ciphertext,
FIPS_AES_CMAC_LENGTH) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
@ -743,6 +802,170 @@ freebl_fips_HMAC_PowerUpSelfTest(void)
return (SECSuccess);
}
SECStatus
freebl_fips_TLS_PowerUpSelfTest(void)
{
static const PRUint8 TLS_known_secret_key[] = {
"Firefox and ThunderBird are awesome!"
};
static const PRUint8 TLS_known_secret_key_length = sizeof TLS_known_secret_key;
/* known tls prf with sha1/md5 */
static const PRUint8 known_TLS_PRF[] = {
0x87, 0x4c, 0xc0, 0xc5, 0x15, 0x14, 0x2b, 0xdc,
0x73, 0x48, 0x9e, 0x88, 0x9d, 0xf5, 0x83, 0x2f,
0x2d, 0x66, 0x1e, 0x78, 0x6c, 0x54, 0x78, 0x29,
0xb9, 0xa4, 0x4c, 0x90, 0x5e, 0xa2, 0xe6, 0x5c,
0xf1, 0x4f, 0xb5, 0x95, 0xa5, 0x54, 0xc0, 0x9f,
0x84, 0x47, 0xb4, 0x4c, 0xda, 0xae, 0x19, 0x29,
0x2b, 0x91, 0x2a, 0x81, 0x9d, 0x3a, 0x30, 0x40,
0xc5, 0xdf, 0xbb, 0xfa, 0xd8, 0x4c, 0xbc, 0x18
};
/* known SHA256 tls mac */
static const PRUint8 known_TLS_SHA256[] = {
0x66, 0xd6, 0x94, 0xd4, 0x0d, 0x32, 0x61, 0x38,
0x26, 0xf6, 0x8b, 0xfe, 0x9e, 0xac, 0xa2, 0xf5,
0x40, 0x52, 0x74, 0x3f, 0xbe, 0xb8, 0xca, 0x94,
0xc3, 0x64, 0xd6, 0x02, 0xf5, 0x88, 0x98, 0x35,
0x73, 0x9f, 0xce, 0xaa, 0x68, 0xe3, 0x7c, 0x93,
0x30, 0x21, 0x45, 0xec, 0xe9, 0x8f, 0x1c, 0x7e,
0xd1, 0x54, 0xf5, 0xbe, 0xff, 0xc8, 0xd7, 0x72,
0x7f, 0x9c, 0x0c, 0x7f, 0xa9, 0xd3, 0x4a, 0xd2
};
#ifdef NSS_FULL_POST
/* known SHA224 tls mac */
static const PRUint8 known_TLS_SHA224[] = {
0xd8, 0x68, 0x15, 0xff, 0xa1, 0xa2, 0x5e, 0x16,
0xce, 0xb1, 0xfd, 0xbd, 0xda, 0x39, 0xbc, 0xa7,
0x27, 0x32, 0x78, 0x94, 0x66, 0xf0, 0x84, 0xcf,
0x46, 0xc0, 0x22, 0x76, 0xdc, 0x6b, 0x2e, 0xed,
0x1d, 0x2d, 0xd2, 0x93, 0xfd, 0xae, 0xca, 0xf9,
0xe0, 0x4c, 0x17, 0x23, 0x22, 0x5a, 0x73, 0x93,
0x20, 0x0a, 0xbd, 0xa0, 0x72, 0xf8, 0x8b, 0x74,
0xfb, 0xf1, 0xab, 0xb7, 0xe0, 0xec, 0x34, 0xc9
};
/* known SHA384 tls mac */
static const PRUint8 known_TLS_SHA384[] = {
0xb2, 0xac, 0x06, 0x10, 0xad, 0x50, 0xd5, 0xdc,
0xdb, 0x01, 0xea, 0xa6, 0x2d, 0x8a, 0x34, 0xb6,
0xeb, 0x84, 0xbc, 0x37, 0xc9, 0x9f, 0xa1, 0x9c,
0xd5, 0xbd, 0x4e, 0x66, 0x16, 0x24, 0xe5, 0x3d,
0xce, 0x74, 0xe0, 0x30, 0x41, 0x5c, 0xdb, 0xb7,
0x52, 0x1d, 0x2d, 0x4d, 0x9b, 0xbe, 0x6b, 0x86,
0xda, 0x8a, 0xca, 0x73, 0x39, 0xb4, 0xc7, 0x8f,
0x03, 0xb1, 0xf9, 0x7e, 0x65, 0xae, 0x17, 0x10
};
/* known SHA512 tls mac */
static const PRUint8 known_TLS_SHA512[] = {
0x73, 0x21, 0x4f, 0x40, 0x81, 0x1e, 0x90, 0xa1,
0x16, 0x40, 0x1e, 0x33, 0x69, 0xc5, 0x00, 0xc7,
0xc4, 0x81, 0xa3, 0x4f, 0xa7, 0xcc, 0x4a, 0xeb,
0x1a, 0x66, 0x00, 0x82, 0x52, 0xe2, 0x2f, 0x69,
0x14, 0x59, 0x05, 0x7c, 0xb0, 0x32, 0xce, 0xcc,
0xb7, 0xc9, 0xab, 0x0f, 0x73, 0x00, 0xe5, 0x52,
0x9d, 0x6b, 0x0e, 0x66, 0x4b, 0xb3, 0x0b, 0x0d,
0x34, 0x53, 0x97, 0x13, 0x84, 0x18, 0x31, 0x7a
};
#endif
SECStatus status;
PRUint8 tls_computed[HASH_LENGTH_MAX];
SECItem secret;
SECItem seed;
SECItem result;
const char *tls_label = "fips test label";
secret.data = (unsigned char *)TLS_known_secret_key;
secret.len = TLS_known_secret_key_length;
seed.data = (unsigned char *)known_hash_message;
seed.len = FIPS_KNOWN_HASH_MESSAGE_LENGTH;
result.data = tls_computed;
result.len = sizeof(tls_computed);
/***************************************************/
/* TLS 1.0 PRF Known Answer Test */
/***************************************************/
status = TLS_PRF(&secret, tls_label, &seed, &result, PR_TRUE);
if ((status != SECSuccess) ||
(result.len != HASH_LENGTH_MAX) ||
(PORT_Memcmp(tls_computed, known_TLS_PRF,
HASH_LENGTH_MAX) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/***************************************************/
/* TLS 1.2 SHA-256 Known Answer Test. */
/***************************************************/
status = TLS_P_hash(HASH_AlgSHA256, &secret, tls_label,
&seed, &result, PR_TRUE);
if ((status != SECSuccess) ||
(result.len != HASH_LENGTH_MAX) ||
(PORT_Memcmp(tls_computed, known_TLS_SHA256,
HASH_LENGTH_MAX) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
#ifdef NSS_FULL_POST
/***************************************************/
/* TLS 1.2 SHA-224 Known Answer Test. */
/***************************************************/
status = TLS_P_hash(HASH_AlgSHA224, &secret, tls_label,
&seed, &result, PR_TRUE);
if ((status != SECSuccess) ||
(result.len != HASH_LENGTH_MAX) ||
(PORT_Memcmp(tls_computed, known_TLS_SHA224,
HASH_LENGTH_MAX) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/***************************************************/
/* TLS 1.2 SHA-384 Known Answer Test. */
/***************************************************/
status = TLS_P_hash(HASH_AlgSHA384, &secret, tls_label,
&seed, &result, PR_TRUE);
if ((status != SECSuccess) ||
(result.len != HASH_LENGTH_MAX) ||
(PORT_Memcmp(tls_computed, known_TLS_SHA384,
HASH_LENGTH_MAX) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/***************************************************/
/* TLS 1.2 SHA-512 Known Answer Test. */
/***************************************************/
status = TLS_P_hash(HASH_AlgSHA512, &secret, tls_label,
&seed, &result, PR_TRUE);
if ((status != SECSuccess) ||
(result.len != HASH_LENGTH_MAX) ||
(PORT_Memcmp(tls_computed, known_TLS_SHA512,
HASH_LENGTH_MAX) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
#endif
return (SECSuccess);
}
static SECStatus
freebl_fips_SHA_PowerUpSelfTest(void)
{
@ -1300,7 +1523,7 @@ freebl_fips_ECDH_Test(ECParams *ecparams)
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,
0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7
};
SECItem ecdh_priv_2, ecdh_pub_1;
@ -1383,7 +1606,8 @@ freebl_fips_EC_PowerUpSelfTest()
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
};
static const ECParams ec_known_P256_Params = {
NULL, ec_params_named, /* arena, type */
NULL,
ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
{ { siBuffer, (unsigned char *)p256_prime, sizeof(p256_prime) } }, /* u.prime */
@ -1418,7 +1642,7 @@ freebl_fips_EC_PowerUpSelfTest()
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,
0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1
};
ECParams ecparams;
@ -1797,12 +2021,6 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
/* SHA-X Power-Up SelfTest(s). */
rv = freebl_fips_SHA_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* RNG Power-Up SelfTest(s). */
rv = freebl_fips_RNG_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
}
@ -1812,6 +2030,12 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
* standalone */
if (tests & DO_REST) {
/* RNG Power-Up SelfTest(s). */
rv = freebl_fips_RNG_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* DES3 Power-Up SelfTest(s). */
rv = freebl_fips_DES3_PowerUpSelfTest();
@ -1839,6 +2063,12 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
/* HMAC SHA-X Power-Up SelfTest(s). */
rv = freebl_fips_HMAC_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* TLS PRF Power-Up SelfTest(s). */
rv = freebl_fips_TLS_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
@ -1986,7 +2216,7 @@ bl_startup_tests(void)
* power on selftest failed.
*/
SECStatus
BL_FIPSEntryOK(PRBool freebl_only)
BL_FIPSEntryOK(PRBool freebl_only, PRBool rerun)
{
#ifdef NSS_NO_INIT_SUPPORT
/* this should only be set on platforms that can't handle one of the INIT
@ -1999,6 +2229,14 @@ BL_FIPSEntryOK(PRBool freebl_only)
bl_startup_tests();
}
#endif
if (rerun) {
/* reset the flags */
self_tests_freebl_ran = PR_FALSE;
self_tests_success = PR_FALSE;
self_tests_success = PR_FALSE;
self_tests_freebl_success = PR_FALSE;
bl_startup_tests();
}
/* if the general self tests succeeded, we're done */
if (self_tests_success) {
return SECSuccess;

View file

@ -17,7 +17,7 @@
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'cc_is_clang==1', {
[ 'cc_is_clang==1 and force_integrated_as!=1', {
'cflags': [
'-no-integrated-as',
],
@ -54,28 +54,55 @@
],
},
{
# TODO: make this so that all hardware accelerated code is in here.
'target_name': 'hw-acc-crypto',
'target_name': 'hw-acc-crypto-avx',
'type': 'static_library',
'sources': [
'verified/Hacl_Chacha20_Vec128.c',
],
# 'sources': [
# All AVX hardware accelerated crypto currently requires x64
# ],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
[ 'target_arch=="x64"', {
'cflags': [
'-mssse3'
'-mssse3',
'-msse4.1',
'-msse4.2'
],
'cflags_mozilla': [
'-mssse3'
'-mssse3',
'-msse4.1',
'-msse4.2',
'-mpclmul',
'-maes',
'-mavx',
],
# GCC doesn't define this.
'defines': [
'__SSSE3__',
],
}],
[ 'OS=="linux" or OS=="android" or OS=="dragonfly" or OS=="freebsd" or \
OS=="netbsd" or OS=="openbsd"', {
'cflags': [
'-mpclmul',
'-maes',
'-mavx',
],
}],
# macOS build doesn't use cflags.
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mssse3',
'-msse4.1',
'-msse4.2',
'-mpclmul',
'-maes',
'-mavx',
],
},
}],
[ 'target_arch=="arm"', {
# Gecko doesn't support non-NEON platform on Android, but tier-3
# platform such as Linux/arm will need it
@ -83,6 +110,82 @@
'-mfpu=neon'
],
}],
[ 'target_arch=="x64"', {
'sources': [
'verified/Hacl_Poly1305_128.c',
'verified/Hacl_Chacha20_Vec128.c',
'verified/Hacl_Chacha20Poly1305_128.c',
],
}],
],
},
{
'target_name': 'hw-acc-crypto-avx2',
'type': 'static_library',
# 'sources': [
# All AVX2 hardware accelerated crypto currently requires x64
# ],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'target_arch=="x64"', {
'cflags': [
'-mssse3',
'-msse4.1',
'-msse4.2'
],
'cflags_mozilla': [
'-mssse3',
'-msse4.1',
'-msse4.2',
'-mpclmul',
'-maes',
'-mavx',
'-mavx2',
],
# GCC doesn't define this.
'defines': [
'__SSSE3__',
],
}],
[ 'OS=="linux" or OS=="android" or OS=="dragonfly" or OS=="freebsd" or \
OS=="netbsd" or OS=="openbsd"', {
'cflags': [
'-mpclmul',
'-maes',
'-mavx',
'-mavx2',
],
}],
# macOS build doesn't use cflags.
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-mssse3',
'-msse4.1',
'-msse4.2',
'-mpclmul',
'-maes',
'-mavx',
'-mavx2',
],
},
}],
[ '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'
],
}],
[ 'target_arch=="x64"', {
'sources': [
'verified/Hacl_Poly1305_256.c',
'verified/Hacl_Chacha20_Vec256.c',
'verified/Hacl_Chacha20Poly1305_256.c',
],
}],
],
},
{
@ -116,6 +219,57 @@
}]
]
},
{
'target_name': 'sha-x86_c_lib',
'type': 'static_library',
'sources': [
'sha256-x86.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'cflags': [
'-msha',
'-mssse3',
'-msse4.1'
],
'cflags_mozilla': [
'-msha',
'-mssse3',
'-msse4.1'
],
'conditions': [
# macOS build doesn't use cflags.
[ 'OS=="mac" or OS=="ios"', {
'xcode_settings': {
'OTHER_CFLAGS': [
'-msha',
'-mssse3',
'-msse4.1'
],
},
}]
]
},
{
'target_name': 'gcm-aes-arm32-neon_c_lib',
'type': 'static_library',
'sources': [
'gcm-arm32-neon.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'cflags': [
'-march=armv7',
'-mfpu=neon',
'<@(softfp_cflags)',
],
'cflags_mozilla': [
'-mfpu=neon',
'<@(softfp_cflags)',
]
},
{
'target_name': 'gcm-aes-aarch64_c_lib',
'type': 'static_library',
@ -136,18 +290,167 @@
'target_name': 'gcm-aes-ppc_c_lib',
'type': 'static_library',
'sources': [
'gcm-ppc.c'
'gcm-ppc.c',
'sha512-p8.s',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'cflags': [
'-mcrypto',
'-maltivec'
'conditions': [
[ 'disable_crypto_vsx==0', {
'cflags': [
'-mcrypto',
'-maltivec'
],
'cflags_mozilla': [
'-mcrypto',
'-maltivec'
],
}, 'disable_crypto_vsx==1', {
'cflags': [
'-maltivec'
],
'cflags_mozilla': [
'-maltivec'
],
}]
]
},
{
'target_name': 'gcm-aes-ppc_lib',
'type': 'static_library',
'sources': [
'ppc-gcm.s',
],
'cflags_mozilla': [
'-mcrypto',
'-maltivec'
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'cc_is_clang==1 and force_integrated_as!=1', {
'cflags': [
'-no-integrated-as',
],
'cflags_mozilla': [
'-no-integrated-as',
],
'asflags_mozilla': [
'-no-integrated-as',
],
}],
],
},
{
'target_name': 'ppc-gcm-wrap-nodepend_c_lib',
'type': 'static_library',
'sources': [
'ppc-gcm-wrap.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'gcm-aes-ppc_lib',
],
},
{
'target_name': 'ppc-gcm-wrap_c_lib',
'type': 'static_library',
'sources': [
'ppc-gcm-wrap.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'gcm-aes-ppc_lib',
],
'defines!': [
'FREEBL_NO_DEPEND',
],
},
{
'target_name': 'gcm-sha512-nodepend-ppc_c_lib',
'type': 'static_library',
'sources': [
'sha512.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'disable_crypto_vsx==0', {
'cflags': [
'-mcrypto',
'-maltivec',
'-mvsx',
'-funroll-loops',
'-fpeel-loops'
],
'cflags_mozilla': [
'-mcrypto',
'-maltivec',
'-mvsx',
'-funroll-loops',
'-fpeel-loops'
],
}, 'disable_crypto_vsx==1', {
'cflags': [
'-maltivec',
'-funroll-loops',
'-fpeel-loops'
],
'cflags_mozilla': [
'-maltivec',
'-funroll-loops',
'-fpeel-loops'
],
}]
]
},
{
'target_name': 'gcm-sha512-ppc_c_lib',
'type': 'static_library',
'sources': [
'sha512.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
],
'conditions': [
[ 'disable_crypto_vsx==0', {
'cflags': [
'-mcrypto',
'-maltivec',
'-mvsx',
'-funroll-loops',
'-fpeel-loops'
],
'cflags_mozilla': [
'-mcrypto',
'-maltivec',
'-mvsx',
'-funroll-loops',
'-fpeel-loops'
],
}, 'disable_crypto_vsx==1', {
'cflags': [
'-maltivec',
'-funroll-loops',
'-fpeel-loops'
],
'cflags_mozilla': [
'-maltivec',
'-funroll-loops',
'-fpeel-loops'
],
}]
],
'defines!': [
'FREEBL_NO_DEPEND',
],
},
{
'target_name': 'chacha20-ppc_lib',
'type': 'static_library',
'sources': [
'chacha20poly1305-ppc.c',
'chacha20-ppc64le.S',
]
},
{
@ -155,6 +458,8 @@
'type': 'static_library',
'sources': [
'aes-armv8.c',
'sha1-armv8.c',
'sha256-armv8.c',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
@ -163,11 +468,13 @@
[ 'target_arch=="arm"', {
'cflags': [
'-march=armv8-a',
'-mfpu=crypto-neon-fp-armv8'
'-mfpu=crypto-neon-fp-armv8',
'<@(softfp_cflags)',
],
'cflags_mozilla': [
'-march=armv8-a',
'-mfpu=crypto-neon-fp-armv8'
'-mfpu=crypto-neon-fp-armv8',
'<@(softfp_cflags)',
],
}, 'target_arch=="arm64" or target_arch=="aarch64"', {
'cflags': [
@ -200,26 +507,61 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
'hw-acc-crypto-avx',
'hw-acc-crypto-avx2',
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
'dependencies': [
'gcm-aes-x86_c_lib',
],
}, 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
}, '(disable_arm_hw_aes==0 or disable_arm_hw_sha1==0 or disable_arm_hw_sha2==0) and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'dependencies': [
'armv8_c_lib'
],
}],
[ '(target_arch=="ia32" or target_arch=="x64") and disable_intel_hw_sha==0', {
'dependencies': [
'sha-x86_c_lib',
],
}],
[ 'disable_arm32_neon==0 and target_arch=="arm"', {
'dependencies': [
'gcm-aes-arm32-neon_c_lib',
],
}],
[ 'disable_arm32_neon==1 and target_arch=="arm"', {
'defines!': [
'NSS_DISABLE_ARM32_NEON',
],
}],
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
'dependencies': [
'gcm-aes-aarch64_c_lib',
],
}],
[ 'target_arch=="ppc64le"', {
[ 'disable_altivec==0 and target_arch=="ppc64"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
'gcm-sha512-ppc_c_lib',
],
}],
[ 'disable_altivec==0 and target_arch=="ppc64le"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
'gcm-sha512-ppc_c_lib',
'chacha20-ppc_lib',
'ppc-gcm-wrap_c_lib',
],
}],
[ 'disable_altivec==1 and (target_arch=="ppc64" or target_arch=="ppc64le")', {
'defines!': [
'NSS_DISABLE_ALTIVEC',
],
}],
[ 'disable_crypto_vsx==1 and (target_arch=="ppc" or target_arch=="ppc64" or target_arch=="ppc64le")', {
'defines!': [
'NSS_DISABLE_CRYPTO_VSX',
],
}],
[ 'OS=="linux"', {
@ -228,6 +570,7 @@
'FREEBL_LOWHASH',
'USE_HW_AES',
'INTEL_GCM',
'PPC_GCM',
],
'conditions': [
[ 'target_arch=="x64"', {
@ -251,7 +594,8 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
'hw-acc-crypto-avx',
'hw-acc-crypto-avx2',
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
@ -263,14 +607,50 @@
'armv8_c_lib',
],
}],
[ '(target_arch=="ia32" or target_arch=="x64") and disable_intel_hw_sha==0', {
'dependencies': [
'sha-x86_c_lib',
],
}],
[ 'disable_arm32_neon==0 and target_arch=="arm"', {
'dependencies': [
'gcm-aes-arm32-neon_c_lib',
],
}],
[ 'disable_arm32_neon==1 and target_arch=="arm"', {
'defines!': [
'NSS_DISABLE_ARM32_NEON',
],
}],
[ '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',
[ 'disable_altivec==0', {
'conditions': [
[ 'target_arch=="ppc64"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
'gcm-sha512-nodepend-ppc_c_lib',
],
}, 'target_arch=="ppc64le"', {
'dependencies': [
'gcm-aes-ppc_c_lib',
'gcm-sha512-nodepend-ppc_c_lib',
'ppc-gcm-wrap-nodepend_c_lib',
],
}],
],
}],
[ 'disable_altivec==1 and (target_arch=="ppc64" or target_arch=="ppc64le")', {
'defines!': [
'NSS_DISABLE_ALTIVEC',
],
}],
[ 'disable_crypto_vsx==1 and (target_arch=="ppc" or target_arch=="ppc64" or target_arch=="ppc64le")', {
'defines!': [
'NSS_DISABLE_CRYPTO_VSX',
],
}],
[ 'OS!="linux"', {
@ -291,7 +671,7 @@
'intel-gcm-wrap_c_lib',
],
}],
[ 'OS=="win" and cc_is_clang==1', {
[ 'OS=="win" and (target_arch=="ia32" or target_arch=="x64") and cc_is_clang==1', {
'dependencies': [
'intel-gcm-wrap_c_lib',
],
@ -321,7 +701,8 @@
'type': 'shared_library',
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
'hw-acc-crypto-avx',
'hw-acc-crypto-avx2',
],
},
{
@ -337,7 +718,8 @@
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
'hw-acc-crypto',
'hw-acc-crypto-avx',
'hw-acc-crypto-avx2',
],
'asflags_mozilla': [
'-mcpu=v9', '-Wa,-xarch=v9a'
@ -379,6 +761,10 @@
'mpi',
'ecl',
'verified',
'verified/internal',
'verified/karamel/include',
'verified/karamel/krmllib/dist/minimal',
'deprecated',
],
'defines': [
'SHLIB_SUFFIX=\"<(dll_suffix)\"',
@ -422,20 +808,49 @@
},
},
}],
[ '(OS=="win" or OS=="mac" or OS=="ios") and (target_arch=="ia32" or target_arch=="x64") and disable_intel_hw_sha==0', {
'defines': [
'USE_HW_SHA2',
],
}],
[ '(OS=="win" or OS=="mac" or OS=="ios") and (target_arch=="arm64" or target_arch=="aarch64") and disable_arm_hw_aes==0', {
'defines': [
'USE_HW_AES',
],
}],
[ '(OS=="win" or OS=="mac" or OS=="ios") and (target_arch=="arm64" or target_arch=="aarch64") and disable_arm_hw_sha1==0', {
'defines': [
'USE_HW_SHA1',
],
}],
[ '(OS=="win" or OS=="mac" or OS=="ios") and (target_arch=="arm64" or target_arch=="aarch64") and disable_arm_hw_sha2==0', {
'defines': [
'USE_HW_SHA2',
],
}],
[ 'cc_use_gnu_ld==1 and OS=="win" and target_arch=="x64"', {
# mingw x64
'defines': [
'MP_IS_LITTLE_ENDIAN',
],
}],
[ 'have_int128_support==1', {
# Poly1305_256 requires the flag to run
['target_arch=="x64"', {
'defines':[
'HACL_CAN_COMPILE_VEC128',
'HACL_CAN_COMPILE_VEC256',
],
}],
# MSVC has no __int128 type. Use emulated int128 and leave
# have_int128_support as-is for Curve25519 impl. selection.
[ 'have_int128_support==1 and (OS!="win" or cc_is_clang==1 or cc_is_gcc==1)', {
'defines': [
# The Makefile does version-tests on GCC, but we're not doing that here.
'HAVE_INT128_SUPPORT',
],
}, {
'defines': [
'KRML_NOUINT128',
'KRML_VERIFIED_UINT128',
],
}],
[ 'OS=="linux"', {
@ -443,6 +858,13 @@
'FREEBL_LOWHASH',
'FREEBL_NO_DEPEND',
],
'conditions': [
[ 'disable_altivec==0 and target_arch=="ppc64le"', {
'defines': [
'PPC_GCM',
],
}],
],
}],
[ 'OS=="linux" or OS=="android"', {
'conditions': [
@ -479,11 +901,26 @@
'ARMHF',
],
}],
[ 'disable_intel_hw_sha==0 and (target_arch=="ia32" or target_arch=="x64")', {
'defines': [
'USE_HW_SHA2',
],
}],
[ 'disable_arm_hw_aes==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'defines': [
'USE_HW_AES',
],
}],
[ 'disable_arm_hw_sha1==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'defines': [
'USE_HW_SHA1',
],
}],
[ 'disable_arm_hw_sha2==0 and (target_arch=="arm" or target_arch=="arm64" or target_arch=="aarch64")', {
'defines': [
'USE_HW_SHA2',
],
}],
],
}],
],
@ -491,17 +928,16 @@
'variables': {
'module': 'nss',
'conditions': [
[ 'OS!="win"', {
'conditions': [
[ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
'have_int128_support%': 1,
}, {
'have_int128_support%': 0,
}],
],
[ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
'have_int128_support%': 1,
}, {
'have_int128_support%': 0,
}],
[ 'target_arch=="arm"', {
# When the compiler uses the softfloat ABI, we want to use the compatible softfp ABI when enabling NEON for these objects.
# Confusingly, __SOFTFP__ is the name of the define for the softfloat ABI, not for the softfp ABI.
'softfp_cflags': '<!(${CC:-cc} -o - -E -dM - ${CFLAGS} < /dev/null | grep __SOFTFP__ > /dev/null && echo -mfloat-abi=softfp || true)',
}],
],
}
}

View file

@ -4,7 +4,6 @@
{
'sources': [
'aeskeywrap.c',
'alg2268.c',
'cmac.c',
'alghmac.c',
'arcfive.c',
@ -57,12 +56,11 @@
'rijndael.c',
'rsa.c',
'rsapkcs.c',
'seed.c',
'sha512.c',
'sha_fast.c',
'shvfy.c',
'sysrand.c',
'tlsprfalg.c',
'secmpi.c',
],
'conditions': [
[ 'OS=="linux" or OS=="android"', {
@ -71,11 +69,11 @@
'sources': [
'arcfour-amd64-gas.s',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_gas.s',
'mpi/mpi_amd64_common.S',
'mpi/mp_comba.c',
],
'conditions': [
[ 'cc_is_clang==1 and fuzz!=1', {
[ 'cc_is_clang==1 and fuzz!=1 and coverage!=1 and force_integrated_as!=1', {
'cflags': [
'-no-integrated-as',
],
@ -98,6 +96,12 @@
'mpi/mpi_arm.c',
],
}],
[ 'target_arch=="ppc64le"', {
'sources': [
'chacha20poly1305-ppc.c',
'chacha20-ppc64le.S',
],
}]
],
}],
[ 'OS=="win"', {
@ -135,54 +139,43 @@
}],
],
}],
['target_arch=="ia32" or target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
['have_int128_support==1', {
'sources': [
# All intel and 64-bit ARM architectures get the 64 bit version.
# All intel x64 and 64-bit ARM architectures get the 64 bit version.
'ecl/curve25519_64.c',
'verified/Hacl_Curve25519.c',
'verified/Hacl_Curve25519_51.c',
],
}, {
'sources': [
# All other architectures get the generic 32 bit implementation (slow!)
# All other architectures get the generic 32 bit implementation.
'ecl/curve25519_32.c',
],
}],
['(target_arch!="ppc64" and target_arch!="ppc64le") or disable_altivec==1', {
'sources': [
# Gyp does not support per-file cflags, so working around like this.
# ppc performance greatly benefits from specific flags.
'sha512.c',
],
}],
[ 'disable_chachapoly==0', {
# The ChaCha20 code is linked in through the static ssse3-crypto lib on
# all platforms that support SSSE3. There are runtime checks in place to
# choose the correct ChaCha implementation at runtime.
'sources': [
'verified/Hacl_Chacha20.c',
'verified/Hacl_Chacha20Poly1305_32.c',
'verified/Hacl_Poly1305_32.c',
],
'conditions': [
[ 'OS!="win"', {
'conditions': [
[ 'target_arch=="x64"', {
'sources': [
'verified/Hacl_Poly1305_64.c',
],
}, {
# !Windows & !x64
'conditions': [
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
'sources': [
'verified/Hacl_Poly1305_64.c',
],
}, {
# !Windows & !x64 & !arm64 & !aarch64
'sources': [
'verified/Hacl_Poly1305_32.c',
],
}],
],
}],
],
}, {
# Windows
'sources': [
'verified/Hacl_Poly1305_32.c',
],
}],
}],
[ 'disable_deprecated_seed==0', {
'sources': [
'deprecated/seed.c',
],
}],
[ 'disable_deprecated_rc2==0', {
'sources': [
'deprecated/alg2268.c',
],
}],
[ 'fuzz==1', {
@ -216,12 +209,21 @@
'MP_ASSEMBLY_SQUARE',
'MP_ASSEMBLY_DIV_2DX1D',
],
}, 'target_arch=="x64"', {
'sources': [
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_common.S',
'mpi/mp_comba.c',
],
'defines': [
'MP_IS_LITTLE_ENDIAN',
'MPI_AMD64',
'MP_ASSEMBLY_MULTIPLY',
'NSS_USE_COMBA',
],
}],
],
}],
[ 'have_int128_support==0', {
'sources': [ 'verified/FStar.c' ],
}],
],
'ldflags': [
'-Wl,-Bsymbolic'

View file

@ -0,0 +1,202 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "blapii.h"
#include "blapit.h"
#include "gcm.h"
#include "secerr.h"
#include "prtypes.h"
#if defined(IS_LITTLE_ENDIAN)
#include <arm_neon.h>
SECStatus
gcm_HashWrite_hw(gcmHashContext *ghash, unsigned char *outbuf)
{
vst1_u8(outbuf, vrev64_u8(vcreate_u8(ghash->x_high)));
vst1_u8(outbuf + 8, vrev64_u8(vcreate_u8(ghash->x_low)));
return SECSuccess;
}
/* Carry-less multiplication. a * b = ret. */
static inline uint8x16_t
clmul(const uint8x8_t a, const uint8x8_t b)
{
uint8x16_t d, e, f, g, h, i, j, k, l, m, n;
uint8x8_t t_high, t_low;
uint8x16_t t0, t1, t2, t3;
const uint8x8_t k16 = vcreate_u8(0xffff);
const uint8x8_t k32 = vcreate_u8(0xffffffff);
const uint8x8_t k48 = vcreate_u8(0xffffffffffff);
// D = A * B
d = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(a),
vreinterpret_p8_u8(b)));
// E = A * B1
e = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(a),
vreinterpret_p8_u8(vext_u8(b, b, 1))));
// F = A1 * B
f = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(vext_u8(a, a, 1)),
vreinterpret_p8_u8(b)));
// G = A * B2
g = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(a),
vreinterpret_p8_u8(vext_u8(b, b, 2))));
// H = A2 * B
h = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(vext_u8(a, a, 2)),
vreinterpret_p8_u8(b)));
// I = A * B3
i = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(a),
vreinterpret_p8_u8(vext_u8(b, b, 3))));
// J = A3 * B
j = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(vext_u8(a, a, 3)),
vreinterpret_p8_u8(b)));
// K = A * B4
k = vreinterpretq_u8_p16(vmull_p8(vreinterpret_p8_u8(a),
vreinterpret_p8_u8(vext_u8(b, b, 4))));
// L = E + F
l = veorq_u8(e, f);
// M = G + H
m = veorq_u8(g, h);
// N = I + J
n = veorq_u8(i, j);
// t0 = (L) (P0 + P1) << 8
t_high = vget_high_u8(l);
t_low = vget_low_u8(l);
t_low = veor_u8(t_low, t_high);
t_high = vand_u8(t_high, k48);
t_low = veor_u8(t_low, t_high);
t0 = vcombine_u8(t_low, t_high);
t0 = vextq_u8(t0, t0, 15);
// t1 = (M) (P2 + P3) << 16
t_high = vget_high_u8(m);
t_low = vget_low_u8(m);
t_low = veor_u8(t_low, t_high);
t_high = vand_u8(t_high, k32);
t_low = veor_u8(t_low, t_high);
t1 = vcombine_u8(t_low, t_high);
t1 = vextq_u8(t1, t1, 14);
// t2 = (N) (P4 + P5) << 24
t_high = vget_high_u8(n);
t_low = vget_low_u8(n);
t_low = veor_u8(t_low, t_high);
t_high = vand_u8(t_high, k16);
t_low = veor_u8(t_low, t_high);
t2 = vcombine_u8(t_low, t_high);
t2 = vextq_u8(t2, t2, 13);
// t3 = (K) (P6 + P7) << 32
t_high = vget_high_u8(k);
t_low = vget_low_u8(k);
t_low = veor_u8(t_low, t_high);
t_high = vdup_n_u8(0);
t3 = vcombine_u8(t_low, t_high);
t3 = vextq_u8(t3, t3, 12);
t0 = veorq_u8(t0, t1);
t2 = veorq_u8(t2, t3);
return veorq_u8(veorq_u8(d, t0), t2);
}
SECStatus
gcm_HashMult_hw(gcmHashContext *ghash, const unsigned char *buf,
unsigned int count)
{
const uint8x8_t h_low = vcreate_u8(ghash->h_low);
const uint8x8_t h_high = vcreate_u8(ghash->h_high);
uint8x16_t ci;
uint8x8_t ci_low;
uint8x8_t ci_high;
uint8x16_t z0, z2, z1a;
uint8x16_t z_high, z_low;
uint8x16_t t;
int64x2_t t1, t2, t3;
uint64x2_t z_low_l, z_low_r, z_high_l, z_high_r;
size_t i;
ci = vcombine_u8(vcreate_u8(ghash->x_low), vcreate_u8(ghash->x_high));
for (i = 0; i < count; i++, buf += 16) {
ci = veorq_u8(ci, vcombine_u8(vrev64_u8(vld1_u8(buf + 8)),
vrev64_u8(vld1_u8(buf))));
ci_high = vget_high_u8(ci);
ci_low = vget_low_u8(ci);
/* Do binary mult ghash->X = C * ghash->H (Karatsuba). */
z0 = clmul(ci_low, h_low);
z2 = clmul(ci_high, h_high);
z1a = clmul(veor_u8(ci_high, ci_low), veor_u8(h_high, h_low));
z1a = veorq_u8(z0, z1a);
z1a = veorq_u8(z2, z1a);
z_high = vcombine_u8(veor_u8(vget_low_u8(z2), vget_high_u8(z1a)),
vget_high_u8(z2));
z_low = vcombine_u8(vget_low_u8(z0),
veor_u8(vget_high_u8(z0), vget_low_u8(z1a)));
/* Shift one (multiply by x) as gcm spec is stupid. */
z_low_l = vshlq_n_u64(vreinterpretq_u64_u8(z_low), 1);
z_low_r = vshrq_n_u64(vreinterpretq_u64_u8(z_low), 63);
z_high_l = vshlq_n_u64(vreinterpretq_u64_u8(z_high), 1);
z_high_r = vshrq_n_u64(vreinterpretq_u64_u8(z_high), 63);
z_low = vreinterpretq_u8_u64(
vcombine_u64(vget_low_u64(z_low_l),
vorr_u64(vget_high_u64(z_low_l),
vget_low_u64(z_low_r))));
z_high = vreinterpretq_u8_u64(
vcombine_u64(vorr_u64(vget_low_u64(z_high_l),
vget_high_u64(z_low_r)),
vorr_u64(vget_high_u64(z_high_l),
vget_low_u64(z_high_r))));
/* Reduce */
t1 = vshlq_n_s64(vreinterpretq_s64_u8(z_low), 57);
t2 = vshlq_n_s64(vreinterpretq_s64_u8(z_low), 62);
t3 = vshlq_n_s64(vreinterpretq_s64_u8(z_low), 63);
t = vreinterpretq_u8_s64(veorq_s64(t1, veorq_s64(t2, t3)));
z_low = vcombine_u8(vget_low_u8(z_low),
veor_u8(vget_high_u8(z_low), vget_low_u8(t)));
z_high = vcombine_u8(veor_u8(vget_low_u8(z_high), vget_high_u8(t)),
vget_high_u8(z_high));
t = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(z_low), 1));
z_high = veorq_u8(z_high, z_low);
z_low = veorq_u8(z_low, t);
t = vreinterpretq_u8_u64(vshrq_n_u64(vreinterpretq_u64_u8(t), 6));
z_low = vreinterpretq_u8_u64(
vshrq_n_u64(vreinterpretq_u64_u8(z_low), 1));
z_low = veorq_u8(z_low, z_high);
ci = veorq_u8(z_low, t);
}
vst1_u8((uint8_t *)&ghash->x_high, vget_high_u8(ci));
vst1_u8((uint8_t *)&ghash->x_low, vget_low_u8(ci));
return SECSuccess;
}
SECStatus
gcm_HashInit_hw(gcmHashContext *ghash)
{
ghash->ghash_mul = gcm_HashMult_hw;
ghash->x_low = 0;
ghash->x_high = 0;
ghash->hw = PR_TRUE;
return SECSuccess;
}
SECStatus
gcm_HashZeroX_hw(gcmHashContext *ghash)
{
ghash->x_low = 0;
ghash->x_high = 0;
return SECSuccess;
}
#endif /* IS_LITTLE_ENDIAN */

View file

@ -9,6 +9,7 @@
#endif
#include "blapii.h"
#include "blapit.h"
#include "blapi.h"
#include "gcm.h"
#include "ctr.h"
#include "secerr.h"
@ -21,6 +22,10 @@
#if defined(__aarch64__) && defined(IS_LITTLE_ENDIAN) && \
(defined(__clang__) || defined(__GNUC__) && __GNUC__ > 6)
#define USE_ARM_GCM
#elif defined(__arm__) && defined(IS_LITTLE_ENDIAN) && \
!defined(NSS_DISABLE_ARM32_NEON)
/* We don't test on big endian platform, so disable this on big endian. */
#define USE_ARM_GCM
#endif
/* Forward declarations */
@ -93,7 +98,11 @@ 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 defined(__aarch64__)
if (arm_pmull_support() && !sw) {
#else
if (arm_neon_support() && !sw) {
#endif
#elif defined(USE_PPC_CRYPTO)
if (ppc_crypto_support() && !sw) {
#else
@ -482,9 +491,12 @@ gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
SECStatus rv;
// Limit AADLen in accordance with SP800-38D
if (sizeof(AADLen) >= 8 && AADLen > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
if (sizeof(AADLen) >= 8) {
unsigned long long AADLen_ull = AADLen;
if (AADLen_ull > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
ghash->cLen = 0;
@ -517,10 +529,18 @@ gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
struct GCMContextStr {
gcmHashContext *ghash_context;
CTRContext ctr_context;
freeblCipherFunc cipher;
void *cipher_context;
unsigned long tagBits;
unsigned char tagKey[MAX_BLOCK_SIZE];
PRBool ctr_context_init;
gcmIVContext gcm_iv;
};
SECStatus gcm_InitCounter(GCMContext *gcm, const unsigned char *iv,
unsigned int ivLen, unsigned int tagBits,
const unsigned char *aad, unsigned int aadLen);
GCMContext *
GCM_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *params)
@ -529,9 +549,7 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
gcmHashContext *ghash = NULL;
unsigned char H[MAX_BLOCK_SIZE];
unsigned int tmp;
PRBool freeCtr = PR_FALSE;
const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params;
CK_AES_CTR_PARAMS ctrParams;
const CK_NSS_GCM_PARAMS *gcmParams = (const CK_NSS_GCM_PARAMS *)params;
SECStatus rv;
#ifdef DISABLE_HW_GCM
const PRBool sw = PR_TRUE;
@ -539,23 +557,12 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
const PRBool sw = PR_FALSE;
#endif
if (gcmParams->ulIvLen == 0) {
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;
}
gcm->cipher = cipher;
gcm->cipher_context = context;
ghash = PORT_ZNewAligned(gcmHashContext, 16, mem);
/* first plug in the ghash context */
@ -570,14 +577,79 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
goto loser;
}
gcm_InitIVContext(&gcm->gcm_iv);
gcm->ctr_context_init = PR_FALSE;
/* if gcmPara/ms is NULL, then we are creating an PKCS #11 MESSAGE
* style context, in which we initialize the key once, then do separate
* iv/aad's for each message. In that case we only initialize the key
* and ghash. We initialize the counter in each separate message */
if (gcmParams == NULL) {
/* OK we are finished with init, if we are doing MESSAGE interface,
* return from here */
return gcm;
}
rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, gcmParams->pAAD,
gcmParams->ulAADLen);
if (rv != SECSuccess) {
goto loser;
}
PORT_Memset(H, 0, AES_BLOCK_SIZE);
gcm->ctr_context_init = PR_TRUE;
return gcm;
loser:
PORT_Memset(H, 0, AES_BLOCK_SIZE);
if (ghash && ghash->mem) {
void *mem = ghash->mem;
PORT_Memset(ghash, 0, sizeof(gcmHashContext));
PORT_Free(mem);
}
if (gcm) {
PORT_ZFree(gcm, sizeof(GCMContext));
}
return NULL;
}
SECStatus
gcm_InitCounter(GCMContext *gcm, const unsigned char *iv, unsigned int ivLen,
unsigned int tagBits, const unsigned char *aad,
unsigned int aadLen)
{
gcmHashContext *ghash = gcm->ghash_context;
unsigned int tmp;
PRBool freeCtr = PR_FALSE;
CK_AES_CTR_PARAMS ctrParams;
SECStatus rv;
/* Verify our parameters here */
if (ivLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
if (tagBits != 128 && tagBits != 120 &&
tagBits != 112 && tagBits != 104 &&
tagBits != 96 && tagBits != 64 &&
tagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
/* fill in the Counter context */
ctrParams.ulCounterBits = 32;
PORT_Memset(ctrParams.cb, 0, sizeof(ctrParams.cb));
if (gcmParams->ulIvLen == 12) {
PORT_Memcpy(ctrParams.cb, gcmParams->pIv, gcmParams->ulIvLen);
if (ivLen == 12) {
PORT_Memcpy(ctrParams.cb, iv, ivLen);
ctrParams.cb[AES_BLOCK_SIZE - 1] = 1;
} else {
rv = gcmHash_Update(ghash, gcmParams->pIv, gcmParams->ulIvLen);
rv = gcmHash_Reset(ghash, NULL, 0);
if (rv != SECSuccess) {
goto loser;
}
rv = gcmHash_Update(ghash, iv, ivLen);
if (rv != SECSuccess) {
goto loser;
}
@ -586,7 +658,7 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
goto loser;
}
}
rv = CTR_InitContext(&gcm->ctr_context, context, cipher,
rv = CTR_InitContext(&gcm->ctr_context, gcm->cipher_context, gcm->cipher,
(unsigned char *)&ctrParams);
if (rv != SECSuccess) {
goto loser;
@ -594,9 +666,10 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
freeCtr = PR_TRUE;
/* fill in the gcm structure */
gcm->tagBits = gcmParams->ulTagBits; /* save for final step */
gcm->tagBits = tagBits; /* save for final step */
/* calculate the final tag key. NOTE: gcm->tagKey is zero to start with.
* if this assumption changes, we would need to explicitly clear it here */
PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey));
rv = CTR_Update(&gcm->ctr_context, gcm->tagKey, &tmp, AES_BLOCK_SIZE,
gcm->tagKey, AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (rv != SECSuccess) {
@ -604,34 +677,34 @@ GCM_CreateContext(void *context, freeblCipherFunc cipher,
}
/* finally mix in the AAD data */
rv = gcmHash_Reset(ghash, gcmParams->pAAD, gcmParams->ulAADLen);
rv = gcmHash_Reset(ghash, aad, aadLen);
if (rv != SECSuccess) {
goto loser;
}
return gcm;
PORT_Memset(&ctrParams, 0, sizeof ctrParams);
return SECSuccess;
loser:
PORT_Memset(&ctrParams, 0, sizeof ctrParams);
if (freeCtr) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
}
if (ghash && ghash->mem) {
PORT_Free(ghash->mem);
}
if (gcm) {
PORT_Free(gcm);
}
return NULL;
return SECFailure;
}
void
GCM_DestroyContext(GCMContext *gcm, PRBool freeit)
{
/* these two are statically allocated and will be freed when we free
void *mem = gcm->ghash_context->mem;
/* ctr_context is statically allocated and will be freed when we free
* gcm. call their destroy functions to free up any locally
* allocated data (like mp_int's) */
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
PORT_Free(gcm->ghash_context->mem);
if (gcm->ctr_context_init) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
}
PORT_Memset(gcm->ghash_context, 0, sizeof(gcmHashContext));
PORT_Free(mem);
PORT_Memset(&gcm->tagBits, 0, sizeof(gcm->tagBits));
PORT_Memset(gcm->tagKey, 0, sizeof(gcm->tagKey));
if (freeit) {
@ -699,6 +772,11 @@ GCM_EncryptUpdate(GCMContext *gcm, unsigned char *outbuf,
return SECFailure;
}
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
if (UINT_MAX - inlen < tagBytes) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
@ -757,6 +835,11 @@ GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
return SECFailure;
}
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
/* get the authentication block */
@ -791,3 +874,298 @@ GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
return CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
}
void
gcm_InitIVContext(gcmIVContext *gcmIv)
{
gcmIv->counter = 0;
gcmIv->max_count = 0;
gcmIv->ivGen = CKG_GENERATE;
gcmIv->ivLen = 0;
gcmIv->fixedBits = 0;
}
/*
* generate the IV on the fly and return it to the application.
* This function keeps a counter, which may be used in the IV
* generation, or may be used in simply to make sure we don't
* generate to many IV's from this same key.
* PKCS #11 defines 4 generating values:
* 1) CKG_NO_GENERATE: just use the passed in IV as it.
* 2) CKG_GENERATE: the application doesn't care what generation
* scheme is use (we default to counter in this code).
* 3) CKG_GENERATE_COUNTER: The IV is the value of a counter.
* 4) CKG_GENERATE_RANDOM: The IV is randomly generated.
* We add a fifth rule:
* 5) CKG_GENERATE_COUNTER_XOR: The Counter value is xor'ed with
* the IV.
* The value fixedBits specifies the number of bits that will be passed
* on from the original IV. The counter or the random data is is loaded
* in the remainder of the IV not covered by fixedBits, overwriting any
* data there. In the xor case the counter is xor'ed with the data in the
* IV. In all cases only bits outside of fixedBits is modified.
* The number of IV's we can generate is restricted by the size of the
* variable part of the IV and the generation algorithm used. Because of
* this, we require subsequent calls on this context to use the same
* generator, IV len, and fixed bits as the first call.
*/
SECStatus
gcm_GenerateIV(gcmIVContext *gcmIv, unsigned char *iv, unsigned int ivLen,
unsigned int fixedBits, CK_GENERATOR_FUNCTION ivGen)
{
unsigned int i;
unsigned int flexBits;
unsigned int ivOffset;
unsigned int ivNewCount;
unsigned char ivMask;
unsigned char ivSave;
SECStatus rv;
if (gcmIv->counter != 0) {
/* If we've already generated a message, make sure all subsequent
* messages are using the same generator */
if ((gcmIv->ivGen != ivGen) || (gcmIv->fixedBits != fixedBits) ||
(gcmIv->ivLen != ivLen)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
} else {
/* remember these values */
gcmIv->ivGen = ivGen;
gcmIv->fixedBits = fixedBits;
gcmIv->ivLen = ivLen;
/* now calculate how may bits of IV we have to supply */
flexBits = ivLen * PR_BITS_PER_BYTE; /* bytes->bits */
/* first make sure we aren't going to overflow */
if (flexBits < fixedBits) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
flexBits -= fixedBits;
/* if we are generating a random number reduce the acceptable bits to
* avoid birthday attacks */
if (ivGen == CKG_GENERATE_RANDOM) {
if (flexBits <= GCMIV_RANDOM_BIRTHDAY_BITS) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* see freebl/blapit.h for how we calculate
* GCMIV_RANDOM_BIRTHDAY_BITS */
flexBits -= GCMIV_RANDOM_BIRTHDAY_BITS;
flexBits = flexBits >> 1;
}
if (flexBits == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Turn those bits into the number of IV's we can safely return */
if (flexBits >= sizeof(gcmIv->max_count) * PR_BITS_PER_BYTE) {
gcmIv->max_count = PR_UINT64(0xffffffffffffffff);
} else {
gcmIv->max_count = PR_UINT64(1) << flexBits;
}
}
/* no generate, accept the IV from the source */
if (ivGen == CKG_NO_GENERATE) {
gcmIv->counter = 1;
return SECSuccess;
}
/* make sure we haven't exceeded the number of IVs we can return
* for this key, generator, and IV size */
if (gcmIv->counter >= gcmIv->max_count) {
/* use a unique error from just bad user input */
PORT_SetError(SEC_ERROR_EXTRA_INPUT);
return SECFailure;
}
/* build to mask to handle the first byte of the IV */
ivOffset = fixedBits / PR_BITS_PER_BYTE;
ivMask = 0xff >> ((8 - (fixedBits & 7)) & 7);
ivNewCount = ivLen - ivOffset;
/* finally generate the IV */
switch (ivGen) {
case CKG_GENERATE: /* default to counter */
case CKG_GENERATE_COUNTER:
iv[ivOffset] = (iv[ivOffset] & ~ivMask) |
(PORT_GET_BYTE_BE(gcmIv->counter, 0, ivNewCount) & ivMask);
for (i = 1; i < ivNewCount; i++) {
iv[ivOffset + i] = PORT_GET_BYTE_BE(gcmIv->counter, i, ivNewCount);
}
break;
/* for TLS 1.3 */
case CKG_GENERATE_COUNTER_XOR:
iv[ivOffset] ^=
(PORT_GET_BYTE_BE(gcmIv->counter, 0, ivNewCount) & ivMask);
for (i = 1; i < ivNewCount; i++) {
iv[ivOffset + i] ^= PORT_GET_BYTE_BE(gcmIv->counter, i, ivNewCount);
}
break;
case CKG_GENERATE_RANDOM:
ivSave = iv[ivOffset] & ~ivMask;
rv = RNG_GenerateGlobalRandomBytes(iv + ivOffset, ivNewCount);
iv[ivOffset] = ivSave | (iv[ivOffset] & ivMask);
if (rv != SECSuccess) {
return rv;
}
break;
}
gcmIv->counter++;
return SECSuccess;
}
SECStatus
GCM_EncryptAEAD(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
SECStatus rv;
unsigned int tagBytes;
unsigned int len;
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
PORT_Assert(blocksize == AES_BLOCK_SIZE);
if (blocksize != AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_EncryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = gcm_GenerateIV(&gcm->gcm_iv, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulIvFixedBits, gcmParams->ivGenerator);
if (rv != SECSuccess) {
return SECFailure;
}
rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
if (rv != SECSuccess) {
return SECFailure;
}
rv = gcmHash_Update(gcm->ghash_context, outbuf, *outlen);
if (rv != SECSuccess) {
PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
*outlen = 0;
return SECFailure;
}
rv = gcm_GetTag(gcm, gcmParams->pTag, &len, tagBytes);
if (rv != SECSuccess) {
PORT_Memset(outbuf, 0, *outlen); /* clear the output buffer */
*outlen = 0;
return SECFailure;
};
return SECSuccess;
}
SECStatus
GCM_DecryptAEAD(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
SECStatus rv;
unsigned int tagBytes;
unsigned char tag[MAX_BLOCK_SIZE];
const unsigned char *intag;
unsigned int len;
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
PORT_Assert(blocksize == AES_BLOCK_SIZE);
if (blocksize != AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_DecryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = gcm_InitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
intag = gcmParams->pTag;
PORT_Assert(tagBytes != 0);
/* verify the block */
rv = gcmHash_Update(gcm->ghash_context, inbuf, inlen);
if (rv != SECSuccess) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
return SECFailure;
}
rv = gcm_GetTag(gcm, tag, &len, AES_BLOCK_SIZE);
if (rv != SECSuccess) {
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
return SECFailure;
}
/* Don't decrypt if we can't authenticate the encrypted data!
* This assumes that if tagBits is may not be a multiple of 8, intag will
* preserve the masked off missing bits. */
if (NSS_SecureMemcmp(tag, intag, tagBytes) != 0) {
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
PORT_SetError(SEC_ERROR_BAD_DATA);
PORT_Memset(tag, 0, sizeof(tag));
return SECFailure;
}
PORT_Memset(tag, 0, sizeof(tag));
/* finish the decryption */
rv = CTR_Update(&gcm->ctr_context, outbuf, outlen, maxout,
inbuf, inlen, AES_BLOCK_SIZE);
CTR_DestroyContext(&gcm->ctr_context, PR_FALSE);
return rv;
}

View file

@ -6,6 +6,7 @@
#define GCM_H 1
#include "blapii.h"
#include "pkcs11t.h"
#include <stdint.h>
#ifdef NSS_X86_OR_X64
@ -30,26 +31,8 @@
#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
#if defined(__powerpc64__)
#include "ppc-crypto.h"
#endif
SEC_BEGIN_PROTOS
@ -78,6 +61,18 @@ SECStatus GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize);
SECStatus GCM_EncryptAEAD(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
SECStatus GCM_DecryptAEAD(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
/* These functions are here only so we can test them */
#define GCM_HASH_LEN_LEN 8 /* gcm hash defines lengths to be 64 bits */
@ -102,6 +97,15 @@ pre_align struct gcmHashContextStr {
gcmHashContext *mem;
} post_align;
typedef struct gcmIVContextStr gcmIVContext;
struct gcmIVContextStr {
PRUint64 counter;
PRUint64 max_count;
CK_GENERATOR_FUNCTION ivGen;
unsigned int fixedBits;
unsigned int ivLen;
};
SECStatus gcmHash_Update(gcmHashContext *ghash, const unsigned char *buf,
unsigned int len);
SECStatus gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H,
@ -111,6 +115,11 @@ SECStatus gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
SECStatus gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout);
void gcm_InitIVContext(gcmIVContext *gcmiv);
SECStatus gcm_GenerateIV(gcmIVContext *gcmIv, unsigned char *iv,
unsigned int ivLen, unsigned int fixedBits,
CK_GENERATOR_FUNCTION ivGen);
SEC_END_PROTOS
#endif

View file

@ -16,34 +16,19 @@
* field. (SHA-384/512 have 128-bit length.) */
#define MAX_HASH_BIT_COUNT_BYTES 16
/* Some utility functions are needed:
*
* These macros return the given value with the MSB copied to all the other
* bits. They use the fact that an arithmetic shift shifts-in the sign bit.
* However, this is not ensured by the C standard so you may need to replace
* them with something else on odd CPUs.
*
* Note: the argument to these macros must be an unsigned int.
* */
#define DUPLICATE_MSB_TO_ALL(x) ((unsigned int)((int)(x) >> (sizeof(int) * 8 - 1)))
#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))
/* constantTimeGE returns 0xff if a>=b and 0x00 otherwise, where a, b <
* MAX_UINT/2. */
static unsigned char
constantTimeGE(unsigned int a, unsigned int b)
{
a -= b;
return DUPLICATE_MSB_TO_ALL(~a);
return PORT_CT_GE(a, b);
}
/* constantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */
static unsigned char
constantTimeEQ8(unsigned char a, unsigned char b)
constantTimeEQ(unsigned char a, unsigned char b)
{
unsigned int c = a ^ b;
c--;
return DUPLICATE_MSB_TO_ALL_8(c);
return PORT_CT_EQ(a, b);
}
/* MAC performs a constant time SSLv3/TLS MAC of |dataLen| bytes of |data|,
@ -223,8 +208,8 @@ MAC(unsigned char *mdOut,
* constant time, to |macOut|. */
for (i = numStartingBlocks; i <= numStartingBlocks + varianceBlocks; i++) {
unsigned char block[HASH_BLOCK_LENGTH_MAX];
unsigned char isBlockA = constantTimeEQ8(i, indexA);
unsigned char isBlockB = constantTimeEQ8(i, indexB);
unsigned char isBlockA = constantTimeEQ(i, indexA);
unsigned char isBlockB = constantTimeEQ(i, indexB);
for (j = 0; j < mdBlockSize; j++) {
unsigned char isPastC = isBlockA & constantTimeGE(j, c);
unsigned char isPastCPlus1 = isBlockA & constantTimeGE(j, c + 1);
@ -289,6 +274,11 @@ MAC(unsigned char *mdOut,
hashObj->end(mdState, mdOut, mdOutLen, mdOutMax);
hashObj->destroy(mdState, PR_TRUE);
PORT_Memset(lengthBytes, 0, sizeof lengthBytes);
PORT_Memset(hmacPad, 0, sizeof hmacPad);
PORT_Memset(firstBlock, 0, sizeof firstBlock);
PORT_Memset(macOut, 0, sizeof macOut);
return SECSuccess;
}

View file

@ -36,8 +36,16 @@ struct intel_AES_GCMContextStr {
unsigned long tagBits;
unsigned long Alen;
unsigned long Mlen;
freeblCipherFunc cipher;
PRBool ctr_context_init;
gcmIVContext gcm_iv;
};
SECStatus intel_aes_gcmInitCounter(intel_AES_GCMContext *gcm,
const unsigned char *iv,
unsigned long ivLen, unsigned long tagBits,
const unsigned char *aad, unsigned long aadLen);
intel_AES_GCMContext *
intel_AES_GCM_CreateContext(void *context,
freeblCipherFunc cipher,
@ -45,38 +53,9 @@ intel_AES_GCM_CreateContext(void *context,
{
intel_AES_GCMContext *gcm = NULL;
AESContext *aes = (AESContext *)context;
const CK_GCM_PARAMS *gcmParams = (const CK_GCM_PARAMS *)params;
unsigned char buff[AES_BLOCK_SIZE]; /* aux buffer */
unsigned long IV_whole_len = gcmParams->ulIvLen & (~0xful);
unsigned int IV_remainder_len = gcmParams->ulIvLen & 0xful;
unsigned long AAD_whole_len = gcmParams->ulAADLen & (~0xful);
unsigned int AAD_remainder_len = gcmParams->ulAADLen & 0xful;
__m128i BSWAP_MASK = _mm_setr_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
__m128i ONE = _mm_set_epi32(0, 0, 0, 1);
unsigned int j;
const CK_NSS_GCM_PARAMS *gcmParams = (const CK_NSS_GCM_PARAMS *)params;
SECStatus rv;
if (gcmParams->ulIvLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
if (gcmParams->ulTagBits != 128 && gcmParams->ulTagBits != 120 &&
gcmParams->ulTagBits != 112 && gcmParams->ulTagBits != 104 &&
gcmParams->ulTagBits != 96 && gcmParams->ulTagBits != 64 &&
gcmParams->ulTagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
// Limit AADLen in accordance with SP800-38D
if (sizeof(AAD_whole_len) >= 8 && AAD_whole_len > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return NULL;
}
gcm = PORT_ZNew(intel_AES_GCMContext);
if (gcm == NULL) {
return NULL;
@ -84,40 +63,102 @@ intel_AES_GCM_CreateContext(void *context,
/* initialize context fields */
gcm->aes_context = aes;
gcm->tagBits = gcmParams->ulTagBits;
gcm->cipher = cipher;
gcm->Alen = 0;
gcm->Mlen = 0;
gcm->ctr_context_init = PR_FALSE;
/* first prepare H and its derivatives for ghash */
intel_aes_gcmINIT(gcm->Htbl, (unsigned char *)aes->k.expandedKey, aes->Nr);
gcm_InitIVContext(&gcm->gcm_iv);
/* if gcmParams is NULL, then we are creating an PKCS #11 MESSAGE
* style context, in which we initialize the key once, then do separate
* iv/aad's for each message. If we are doing that kind of operation,
* we've finished with init here. We'll init the Counter in each AEAD
* call */
if (gcmParams == NULL) {
return gcm;
}
rv = intel_aes_gcmInitCounter(gcm, gcmParams->pIv,
gcmParams->ulIvLen, gcmParams->ulTagBits,
gcmParams->pAAD, gcmParams->ulAADLen);
if (rv != SECSuccess) {
PORT_Free(gcm);
return NULL;
}
gcm->ctr_context_init = PR_TRUE;
return gcm;
}
SECStatus
intel_aes_gcmInitCounter(intel_AES_GCMContext *gcm,
const unsigned char *iv, unsigned long ivLen,
unsigned long tagBits,
const unsigned char *aad, unsigned long aadLen)
{
unsigned char buff[AES_BLOCK_SIZE]; /* aux buffer */
unsigned long IV_whole_len = ivLen & (~0xful);
unsigned int IV_remainder_len = ivLen & 0xful;
unsigned long AAD_whole_len = aadLen & (~0xful);
unsigned int AAD_remainder_len = aadLen & 0xful;
unsigned int j;
__m128i BSWAP_MASK = _mm_setr_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
__m128i ONE = _mm_set_epi32(0, 0, 0, 1);
SECStatus rv;
if (ivLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (tagBits != 128 && tagBits != 120 && tagBits != 112 &&
tagBits != 104 && tagBits != 96 && tagBits != 64 &&
tagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
gcm->tagBits = tagBits;
/* reset the aad and message length counters */
gcm->Alen = 0;
gcm->Mlen = 0;
// Limit AADLen in accordance with SP800-38D
if (sizeof(AAD_whole_len) >= 8 && AAD_whole_len > (1ULL << 61) - 1) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
/* Initial TAG value is zero */
_mm_storeu_si128((__m128i *)gcm->T, _mm_setzero_si128());
_mm_storeu_si128((__m128i *)gcm->X0, _mm_setzero_si128());
/* Init the counter */
if (gcmParams->ulIvLen == 12) {
if (ivLen == 12) {
_mm_storeu_si128((__m128i *)gcm->CTR,
_mm_setr_epi32(((unsigned int *)gcmParams->pIv)[0],
((unsigned int *)gcmParams->pIv)[1],
((unsigned int *)gcmParams->pIv)[2],
_mm_setr_epi32(((unsigned int *)iv)[0],
((unsigned int *)iv)[1],
((unsigned int *)iv)[2],
0x01000000));
} else {
/* If IV size is not 96 bits, then the initial counter value is GHASH
* of the IV */
intel_aes_gcmAAD(gcm->Htbl, gcmParams->pIv, IV_whole_len, gcm->T);
intel_aes_gcmAAD(gcm->Htbl, (unsigned char *)iv, IV_whole_len, gcm->T);
/* Partial block */
if (IV_remainder_len) {
PORT_Memset(buff, 0, AES_BLOCK_SIZE);
PORT_Memcpy(buff, gcmParams->pIv + IV_whole_len, IV_remainder_len);
PORT_Memcpy(buff, iv + IV_whole_len, IV_remainder_len);
intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T);
}
intel_aes_gcmTAG(
gcm->Htbl,
gcm->T,
gcmParams->ulIvLen,
ivLen,
0,
gcm->X0,
gcm->CTR);
@ -128,10 +169,10 @@ intel_AES_GCM_CreateContext(void *context,
/* Encrypt the initial counter, will be used to encrypt the GHASH value,
* in the end */
rv = (*cipher)(context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR,
AES_BLOCK_SIZE, AES_BLOCK_SIZE);
rv = (*gcm->cipher)(gcm->aes_context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR,
AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (rv != SECSuccess) {
goto loser;
return SECFailure;
}
/* Promote the counter by 1 */
@ -141,18 +182,14 @@ intel_AES_GCM_CreateContext(void *context,
* creation from the AAD, because that would allow to reuse the H, which
* only changes when the AES key changes, and not every package, like the
* IV and AAD */
intel_aes_gcmAAD(gcm->Htbl, gcmParams->pAAD, AAD_whole_len, gcm->T);
intel_aes_gcmAAD(gcm->Htbl, (unsigned char *)aad, AAD_whole_len, gcm->T);
if (AAD_remainder_len) {
PORT_Memset(buff, 0, AES_BLOCK_SIZE);
PORT_Memcpy(buff, gcmParams->pAAD + AAD_whole_len, AAD_remainder_len);
PORT_Memcpy(buff, aad + AAD_whole_len, AAD_remainder_len);
intel_aes_gcmAAD(gcm->Htbl, buff, AES_BLOCK_SIZE, gcm->T);
}
gcm->Alen += gcmParams->ulAADLen;
return gcm;
loser:
PORT_Free(gcm);
return NULL;
gcm->Alen += aadLen;
return SECSuccess;
}
void
@ -177,9 +214,16 @@ intel_AES_GCM_EncryptUpdate(intel_AES_GCMContext *gcm,
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
if (sizeof(inlen) > 4) {
unsigned long long inlen_ull = inlen;
if (inlen_ull >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
@ -229,6 +273,11 @@ intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm,
unsigned char T[AES_BLOCK_SIZE];
const unsigned char *intag;
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
/* get the authentication block */
@ -242,10 +291,12 @@ intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm,
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
if (sizeof(inlen) > 4) {
unsigned long long inlen_ull = inlen;
if (inlen_ull >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
if (maxout < inlen) {
@ -281,4 +332,144 @@ intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm,
return SECSuccess;
}
SECStatus
intel_AES_GCM_EncryptAEAD(intel_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
SECStatus rv;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4) {
unsigned long long inlen_ull = inlen;
if (inlen_ull >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_EncryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = gcm_GenerateIV(&gcm->gcm_iv, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulIvFixedBits, gcmParams->ivGenerator);
if (rv != SECSuccess) {
return SECFailure;
}
rv = intel_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
intel_aes_gcmENC(inbuf, outbuf, gcm, inlen);
gcm->Mlen += inlen;
intel_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
*outlen = inlen;
PORT_Memcpy(gcmParams->pTag, T, tagBytes);
return SECSuccess;
}
SECStatus
intel_AES_GCM_DecryptAEAD(intel_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
const unsigned char *intag;
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
SECStatus rv;
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_DecryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4) {
unsigned long long inlen_ull = inlen;
if (inlen_ull >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = intel_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
intag = gcmParams->pTag;
PORT_Assert(tagBytes != 0);
intel_aes_gcmDEC(inbuf, outbuf, gcm, inlen);
gcm->Mlen += inlen;
intel_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) {
memset(outbuf, 0, inlen);
*outlen = 0;
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
*outlen = inlen;
return SECSuccess;
}
#endif

View file

@ -40,6 +40,20 @@ SECStatus intel_AES_GCM_DecryptUpdate(intel_AES_GCMContext *gcm, unsigned char *
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize);
SECStatus intel_AES_GCM_EncryptAEAD(intel_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
SECStatus intel_AES_GCM_DecryptAEAD(intel_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
/* Prototypes of functions in the assembler file for fast AES-GCM, using
Intel AES-NI and CLMUL-NI, as described in [1]

View file

@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
extern int FREEBL_InitStubs(void);
#endif
@ -14,323 +15,370 @@ extern int FREEBL_InitStubs(void);
#include "alghmac.h"
#include "hmacct.h"
#include "blapii.h"
#include "secerr.h"
static const struct FREEBLVectorStr vector =
{
SECStatus
FREEBL_Deprecated(void)
{
sizeof vector,
FREEBL_VERSION,
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
return SECFailure;
}
RSA_NewKey,
RSA_PublicKeyOp,
RSA_PrivateKeyOp,
DSA_NewKey,
DSA_SignDigest,
DSA_VerifyDigest,
DSA_NewKeyFromSeed,
DSA_SignDigestWithSeed,
DH_GenParam,
DH_NewKey,
DH_Derive,
KEA_Derive,
KEA_Verify,
RC4_CreateContext,
RC4_DestroyContext,
RC4_Encrypt,
RC4_Decrypt,
RC2_CreateContext,
RC2_DestroyContext,
RC2_Encrypt,
RC2_Decrypt,
RC5_CreateContext,
RC5_DestroyContext,
RC5_Encrypt,
RC5_Decrypt,
DES_CreateContext,
DES_DestroyContext,
DES_Encrypt,
DES_Decrypt,
AES_CreateContext,
AES_DestroyContext,
AES_Encrypt,
AES_Decrypt,
MD5_Hash,
MD5_HashBuf,
MD5_NewContext,
MD5_DestroyContext,
MD5_Begin,
MD5_Update,
MD5_End,
MD5_FlattenSize,
MD5_Flatten,
MD5_Resurrect,
MD5_TraceState,
MD2_Hash,
MD2_NewContext,
MD2_DestroyContext,
MD2_Begin,
MD2_Update,
MD2_End,
MD2_FlattenSize,
MD2_Flatten,
MD2_Resurrect,
SHA1_Hash,
SHA1_HashBuf,
SHA1_NewContext,
SHA1_DestroyContext,
SHA1_Begin,
SHA1_Update,
SHA1_End,
SHA1_TraceState,
SHA1_FlattenSize,
SHA1_Flatten,
SHA1_Resurrect,
RNG_RNGInit,
RNG_RandomUpdate,
RNG_GenerateGlobalRandomBytes,
RNG_RNGShutdown,
PQG_ParamGen,
PQG_ParamGenSeedLen,
PQG_VerifyParams,
static const struct FREEBLVectorStr vector = {
/* End of Version 3.001. */
sizeof vector,
FREEBL_VERSION,
RSA_PrivateKeyOpDoubleChecked,
RSA_PrivateKeyCheck,
BL_Cleanup,
RSA_NewKey,
RSA_PublicKeyOp,
RSA_PrivateKeyOp,
DSA_NewKey,
DSA_SignDigest,
DSA_VerifyDigest,
DSA_NewKeyFromSeed,
DSA_SignDigestWithSeed,
DH_GenParam,
DH_NewKey,
DH_Derive,
KEA_Derive,
KEA_Verify,
RC4_CreateContext,
RC4_DestroyContext,
RC4_Encrypt,
RC4_Decrypt,
#ifndef NSS_DISABLE_DEPRECATED_RC2
RC2_CreateContext,
RC2_DestroyContext,
RC2_Encrypt,
RC2_Decrypt,
#else
(F_RC2_CreateContext)FREEBL_Deprecated,
(F_RC2_DestroyContext)FREEBL_Deprecated,
(F_RC2_Encrypt)FREEBL_Deprecated,
(F_RC2_Decrypt)FREEBL_Deprecated,
#endif
RC5_CreateContext,
RC5_DestroyContext,
RC5_Encrypt,
RC5_Decrypt,
DES_CreateContext,
DES_DestroyContext,
DES_Encrypt,
DES_Decrypt,
AES_CreateContext,
AES_DestroyContext,
AES_Encrypt,
AES_Decrypt,
MD5_Hash,
MD5_HashBuf,
MD5_NewContext,
MD5_DestroyContext,
MD5_Begin,
MD5_Update,
MD5_End,
MD5_FlattenSize,
MD5_Flatten,
MD5_Resurrect,
MD5_TraceState,
MD2_Hash,
MD2_NewContext,
MD2_DestroyContext,
MD2_Begin,
MD2_Update,
MD2_End,
MD2_FlattenSize,
MD2_Flatten,
MD2_Resurrect,
SHA1_Hash,
SHA1_HashBuf,
SHA1_NewContext,
SHA1_DestroyContext,
SHA1_Begin,
SHA1_Update,
SHA1_End,
SHA1_TraceState,
SHA1_FlattenSize,
SHA1_Flatten,
SHA1_Resurrect,
RNG_RNGInit,
RNG_RandomUpdate,
RNG_GenerateGlobalRandomBytes,
RNG_RNGShutdown,
PQG_ParamGen,
PQG_ParamGenSeedLen,
PQG_VerifyParams,
/* End of Version 3.002. */
/* End of Version 3.001. */
SHA256_NewContext,
SHA256_DestroyContext,
SHA256_Begin,
SHA256_Update,
SHA256_End,
SHA256_HashBuf,
SHA256_Hash,
SHA256_TraceState,
SHA256_FlattenSize,
SHA256_Flatten,
SHA256_Resurrect,
RSA_PrivateKeyOpDoubleChecked,
RSA_PrivateKeyCheck,
BL_Cleanup,
SHA512_NewContext,
SHA512_DestroyContext,
SHA512_Begin,
SHA512_Update,
SHA512_End,
SHA512_HashBuf,
SHA512_Hash,
SHA512_TraceState,
SHA512_FlattenSize,
SHA512_Flatten,
SHA512_Resurrect,
/* End of Version 3.002. */
SHA384_NewContext,
SHA384_DestroyContext,
SHA384_Begin,
SHA384_Update,
SHA384_End,
SHA384_HashBuf,
SHA384_Hash,
SHA384_TraceState,
SHA384_FlattenSize,
SHA384_Flatten,
SHA384_Resurrect,
SHA256_NewContext,
SHA256_DestroyContext,
SHA256_Begin,
SHA256_Update,
SHA256_End,
SHA256_HashBuf,
SHA256_Hash,
SHA256_TraceState,
SHA256_FlattenSize,
SHA256_Flatten,
SHA256_Resurrect,
/* End of Version 3.003. */
SHA512_NewContext,
SHA512_DestroyContext,
SHA512_Begin,
SHA512_Update,
SHA512_End,
SHA512_HashBuf,
SHA512_Hash,
SHA512_TraceState,
SHA512_FlattenSize,
SHA512_Flatten,
SHA512_Resurrect,
AESKeyWrap_CreateContext,
AESKeyWrap_DestroyContext,
AESKeyWrap_Encrypt,
AESKeyWrap_Decrypt,
SHA384_NewContext,
SHA384_DestroyContext,
SHA384_Begin,
SHA384_Update,
SHA384_End,
SHA384_HashBuf,
SHA384_Hash,
SHA384_TraceState,
SHA384_FlattenSize,
SHA384_Flatten,
SHA384_Resurrect,
/* End of Version 3.004. */
/* End of Version 3.003. */
BLAPI_SHVerify,
BLAPI_VerifySelf,
AESKeyWrap_CreateContext,
AESKeyWrap_DestroyContext,
AESKeyWrap_Encrypt,
AESKeyWrap_Decrypt,
/* End of Version 3.005. */
/* End of Version 3.004. */
EC_NewKey,
EC_NewKeyFromSeed,
EC_ValidatePublicKey,
ECDH_Derive,
ECDSA_SignDigest,
ECDSA_VerifyDigest,
ECDSA_SignDigestWithSeed,
BLAPI_SHVerify,
BLAPI_VerifySelf,
/* End of Version 3.006. */
/* End of Version 3.007. */
/* End of Version 3.005. */
AES_InitContext,
AESKeyWrap_InitContext,
DES_InitContext,
RC2_InitContext,
RC4_InitContext,
EC_NewKey,
EC_NewKeyFromSeed,
EC_ValidatePublicKey,
ECDH_Derive,
ECDSA_SignDigest,
ECDSA_VerifyDigest,
ECDSA_SignDigestWithSeed,
AES_AllocateContext,
AESKeyWrap_AllocateContext,
DES_AllocateContext,
RC2_AllocateContext,
RC4_AllocateContext,
/* End of Version 3.006. */
/* End of Version 3.007. */
MD2_Clone,
MD5_Clone,
SHA1_Clone,
SHA256_Clone,
SHA384_Clone,
SHA512_Clone,
AES_InitContext,
AESKeyWrap_InitContext,
DES_InitContext,
#ifndef NSS_DISABLE_DEPRECATED_RC2
RC2_InitContext,
#else
(F_RC2_InitContext)FREEBL_Deprecated,
#endif
RC4_InitContext,
TLS_PRF,
HASH_GetRawHashObject,
AES_AllocateContext,
AESKeyWrap_AllocateContext,
DES_AllocateContext,
#ifndef NSS_DISABLE_DEPRECATED_RC2
RC2_AllocateContext,
#else
(F_RC2_AllocateContext)FREEBL_Deprecated,
#endif
RC4_AllocateContext,
HMAC_Create,
HMAC_Init,
HMAC_Begin,
HMAC_Update,
HMAC_Clone,
HMAC_Finish,
HMAC_Destroy,
MD2_Clone,
MD5_Clone,
SHA1_Clone,
SHA256_Clone,
SHA384_Clone,
SHA512_Clone,
RNG_SystemInfoForRNG,
TLS_PRF,
HASH_GetRawHashObject,
/* End of Version 3.008. */
HMAC_Create,
HMAC_Init,
HMAC_Begin,
HMAC_Update,
HMAC_Clone,
HMAC_Finish,
HMAC_Destroy,
FIPS186Change_GenerateX,
FIPS186Change_ReduceModQForDSA,
RNG_SystemInfoForRNG,
/* End of Version 3.009. */
Camellia_InitContext,
Camellia_AllocateContext,
Camellia_CreateContext,
Camellia_DestroyContext,
Camellia_Encrypt,
Camellia_Decrypt,
/* End of Version 3.008. */
PQG_DestroyParams,
PQG_DestroyVerify,
FIPS186Change_GenerateX,
FIPS186Change_ReduceModQForDSA,
/* End of Version 3.010. */
/* End of Version 3.009. */
Camellia_InitContext,
Camellia_AllocateContext,
Camellia_CreateContext,
Camellia_DestroyContext,
Camellia_Encrypt,
Camellia_Decrypt,
SEED_InitContext,
SEED_AllocateContext,
SEED_CreateContext,
SEED_DestroyContext,
SEED_Encrypt,
SEED_Decrypt,
PQG_DestroyParams,
PQG_DestroyVerify,
BL_Init,
BL_SetForkState,
/* End of Version 3.010. */
PRNGTEST_Instantiate,
PRNGTEST_Reseed,
PRNGTEST_Generate,
#ifndef NSS_DISABLE_DEPRECATED_SEED
SEED_InitContext,
SEED_AllocateContext,
SEED_CreateContext,
SEED_DestroyContext,
SEED_Encrypt,
SEED_Decrypt,
#else
(F_SEED_InitContext)FREEBL_Deprecated,
(F_SEED_AllocateContext)FREEBL_Deprecated,
(F_SEED_CreateContext)FREEBL_Deprecated,
(F_SEED_DestroyContext)FREEBL_Deprecated,
(F_SEED_Encrypt)FREEBL_Deprecated,
(F_SEED_Decrypt)FREEBL_Deprecated,
#endif /* NSS_DISABLE_DEPRECATED_SEED */
PRNGTEST_Uninstantiate,
BL_Init,
BL_SetForkState,
/* End of Version 3.011. */
PRNGTEST_Instantiate,
PRNGTEST_Reseed,
PRNGTEST_Generate,
RSA_PopulatePrivateKey,
PRNGTEST_Uninstantiate,
DSA_NewRandom,
/* End of Version 3.011. */
JPAKE_Sign,
JPAKE_Verify,
JPAKE_Round2,
JPAKE_Final,
RSA_PopulatePrivateKey,
/* End of Version 3.012 */
DSA_NewRandom,
TLS_P_hash,
SHA224_NewContext,
SHA224_DestroyContext,
SHA224_Begin,
SHA224_Update,
SHA224_End,
SHA224_HashBuf,
SHA224_Hash,
SHA224_TraceState,
SHA224_FlattenSize,
SHA224_Flatten,
SHA224_Resurrect,
SHA224_Clone,
BLAPI_SHVerifyFile,
JPAKE_Sign,
JPAKE_Verify,
JPAKE_Round2,
JPAKE_Final,
/* End of Version 3.013 */
/* End of Version 3.012 */
PQG_ParamGenV2,
PRNGTEST_RunHealthTests,
TLS_P_hash,
SHA224_NewContext,
SHA224_DestroyContext,
SHA224_Begin,
SHA224_Update,
SHA224_End,
SHA224_HashBuf,
SHA224_Hash,
SHA224_TraceState,
SHA224_FlattenSize,
SHA224_Flatten,
SHA224_Resurrect,
SHA224_Clone,
BLAPI_SHVerifyFile,
/* End of Version 3.014 */
/* End of Version 3.013 */
HMAC_ConstantTime,
SSLv3_MAC_ConstantTime,
PQG_ParamGenV2,
PRNGTEST_RunHealthTests,
/* End of Version 3.015 */
/* End of Version 3.014 */
RSA_SignRaw,
RSA_CheckSignRaw,
RSA_CheckSignRecoverRaw,
RSA_EncryptRaw,
RSA_DecryptRaw,
RSA_EncryptOAEP,
RSA_DecryptOAEP,
RSA_EncryptBlock,
RSA_DecryptBlock,
RSA_SignPSS,
RSA_CheckSignPSS,
RSA_Sign,
RSA_CheckSign,
RSA_CheckSignRecover,
HMAC_ConstantTime,
SSLv3_MAC_ConstantTime,
/* End of Version 3.016 */
/* End of Version 3.015 */
EC_FillParams,
EC_DecodeParams,
EC_CopyParams,
RSA_SignRaw,
RSA_CheckSignRaw,
RSA_CheckSignRecoverRaw,
RSA_EncryptRaw,
RSA_DecryptRaw,
RSA_EncryptOAEP,
RSA_DecryptOAEP,
RSA_EncryptBlock,
RSA_DecryptBlock,
RSA_SignPSS,
RSA_CheckSignPSS,
RSA_Sign,
RSA_CheckSign,
RSA_CheckSignRecover,
/* End of Version 3.017 */
/* End of Version 3.016 */
ChaCha20Poly1305_InitContext,
ChaCha20Poly1305_CreateContext,
ChaCha20Poly1305_DestroyContext,
ChaCha20Poly1305_Seal,
ChaCha20Poly1305_Open,
EC_FillParams,
EC_DecodeParams,
EC_CopyParams,
/* End of Version 3.018 */
/* End of Version 3.017 */
EC_GetPointSize,
ChaCha20Poly1305_InitContext,
ChaCha20Poly1305_CreateContext,
ChaCha20Poly1305_DestroyContext,
ChaCha20Poly1305_Seal,
ChaCha20Poly1305_Open,
/* End of Version 3.019 */
/* End of Version 3.018 */
BLAKE2B_Hash,
BLAKE2B_HashBuf,
BLAKE2B_MAC_HashBuf,
BLAKE2B_NewContext,
BLAKE2B_DestroyContext,
BLAKE2B_Begin,
BLAKE2B_MAC_Begin,
BLAKE2B_Update,
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
BLAKE2B_Resurrect,
EC_GetPointSize,
/* End of Version 3.020 */
/* End of Version 3.019 */
ChaCha20_Xor,
BLAKE2B_Hash,
BLAKE2B_HashBuf,
BLAKE2B_MAC_HashBuf,
BLAKE2B_NewContext,
BLAKE2B_DestroyContext,
BLAKE2B_Begin,
BLAKE2B_MAC_Begin,
BLAKE2B_Update,
BLAKE2B_End,
BLAKE2B_FlattenSize,
BLAKE2B_Flatten,
BLAKE2B_Resurrect,
/* End of version 3.021 */
/* End of Version 3.020 */
CMAC_Init,
CMAC_Create,
CMAC_Begin,
CMAC_Update,
CMAC_Finish,
CMAC_Destroy
ChaCha20_Xor,
/* End of version 3.022 */
};
/* End of version 3.021 */
CMAC_Init,
CMAC_Create,
CMAC_Begin,
CMAC_Update,
CMAC_Finish,
CMAC_Destroy,
/* End of version 3.022 */
ChaCha20Poly1305_Encrypt,
ChaCha20Poly1305_Decrypt,
AES_AEAD,
AESKeyWrap_EncryptKWP,
AESKeyWrap_DecryptKWP,
/* End of version 3.023 */
KEA_PrimeCheck,
/* End of version 3.024 */
ChaCha20_InitContext,
ChaCha20_CreateContext,
ChaCha20_DestroyContext
/* End of version 3.025 */
};
const FREEBLVector*
FREEBL_GetVector(void)
@ -360,21 +408,20 @@ FREEBL_GetVector(void)
}
#ifdef FREEBL_LOWHASH
static const struct NSSLOWVectorStr nssvector =
{
sizeof nssvector,
NSSLOW_VERSION,
FREEBL_GetVector,
NSSLOW_Init,
NSSLOW_Shutdown,
NSSLOW_Reset,
NSSLOWHASH_NewContext,
NSSLOWHASH_Begin,
NSSLOWHASH_Update,
NSSLOWHASH_End,
NSSLOWHASH_Destroy,
NSSLOWHASH_Length
};
static const struct NSSLOWVectorStr nssvector = {
sizeof nssvector,
NSSLOW_VERSION,
FREEBL_GetVector,
NSSLOW_Init,
NSSLOW_Shutdown,
NSSLOW_Reset,
NSSLOWHASH_NewContext,
NSSLOWHASH_Begin,
NSSLOWHASH_Update,
NSSLOWHASH_End,
NSSLOWHASH_Destroy,
NSSLOWHASH_Length
};
const NSSLOWVector*
NSSLOW_GetVector(void)

View file

@ -236,6 +236,14 @@ KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
return (vector->p_KEA_Verify)(Y, prime, subPrime);
}
PRBool
KEA_PrimeCheck(SECItem *prime)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return PR_FALSE;
return (vector->p_KEA_PrimeCheck)(prime);
}
RC4Context *
RC4_CreateContext(const unsigned char *key, int len)
{
@ -280,7 +288,11 @@ RC2_CreateContext(const unsigned char *key, unsigned int len,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
#ifndef NSS_DISABLE_DEPRECATED_RC2
return (vector->p_RC2_CreateContext)(key, len, iv, mode, effectiveKeyLen);
#else
return NULL;
#endif
}
void
@ -288,7 +300,11 @@ RC2_DestroyContext(RC2Context *cx, PRBool freeit)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
#ifndef NSS_DISABLE_DEPRECATED_RC2
(vector->p_RC2_DestroyContext)(cx, freeit);
#else
return;
#endif
}
SECStatus
@ -298,8 +314,12 @@ RC2_Encrypt(RC2Context *cx, unsigned char *output, unsigned int *outputLen,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_RC2
return (vector->p_RC2_Encrypt)(cx, output, outputLen, maxOutputLen, input,
inputLen);
#else
return SECFailure;
#endif
}
SECStatus
@ -309,8 +329,12 @@ RC2_Decrypt(RC2Context *cx, unsigned char *output, unsigned int *outputLen,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_RC2
return (vector->p_RC2_Decrypt)(cx, output, outputLen, maxOutputLen, input,
inputLen);
#else
return SECFailure;
#endif
}
RC5Context *
@ -396,7 +420,11 @@ SEED_CreateContext(const unsigned char *key, const unsigned char *iv,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
#ifndef NSS_DISABLE_DEPRECATED_SEED
return (vector->p_SEED_CreateContext)(key, iv, mode, encrypt);
#else
return NULL;
#endif
}
void
@ -404,7 +432,11 @@ SEED_DestroyContext(SEEDContext *cx, PRBool freeit)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
#ifndef NSS_DISABLE_DEPRECATED_SEED
(vector->p_SEED_DestroyContext)(cx, freeit);
#else
return;
#endif
}
SECStatus
@ -414,8 +446,12 @@ SEED_Encrypt(SEEDContext *cx, unsigned char *output, unsigned int *outputLen,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_SEED
return (vector->p_SEED_Encrypt)(cx, output, outputLen, maxOutputLen, input,
inputLen);
#else
return SECFailure;
#endif
}
SECStatus
@ -425,8 +461,12 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *output, unsigned int *outputLen,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_SEED
return (vector->p_SEED_Decrypt)(cx, output, outputLen, maxOutputLen, input,
inputLen);
#else
return SECFailure;
#endif
}
AESContext *
@ -470,6 +510,19 @@ AES_Decrypt(AESContext *cx, unsigned char *output,
input, inputLen);
}
SECStatus
AES_AEAD(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
void *params, unsigned int paramsLen,
const unsigned char *aad, unsigned int aadLen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_AES_AEAD)(cx, output, outputLen, maxOutputLen, input,
inputLen, params, paramsLen, aad, aadLen);
}
SECStatus
MD5_Hash(unsigned char *dest, const char *src)
{
@ -1125,6 +1178,7 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
return vector->p_AESKeyWrap_Encrypt(cx, output, outputLen, maxOutputLen,
input, inputLen);
}
SECStatus
AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
@ -1136,6 +1190,28 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
input, inputLen);
}
SECStatus
AESKeyWrap_EncryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return vector->p_AESKeyWrap_EncryptKWP(cx, output, outputLen, maxOutputLen,
input, inputLen);
}
SECStatus
AESKeyWrap_DecryptKWP(AESKeyWrapContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return vector->p_AESKeyWrap_DecryptKWP(cx, output, outputLen, maxOutputLen,
input, inputLen);
}
PRBool
BLAPI_SHVerify(const char *name, PRFuncPtr addr)
{
@ -1255,7 +1331,11 @@ RC2_AllocateContext(void)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
#ifndef NSS_DISABLE_DEPRECATED_RC2
return (vector->p_RC2_AllocateContext)();
#else
return NULL;
#endif
}
RC4Context *
@ -1305,7 +1385,11 @@ SEED_InitContext(SEEDContext *cx, const unsigned char *key,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_SEED
return (vector->p_SEED_InitContext)(cx, key, keylen, iv, mode, encrypt, xtra);
#else
return SECFailure;
#endif
}
SECStatus
@ -1315,8 +1399,12 @@ RC2_InitContext(RC2Context *cx, const unsigned char *key,
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
#ifndef NSS_DISABLE_DEPRECATED_RC2
return (vector->p_RC2_InitContext)(cx, key, keylen, iv, mode,
effectiveKeyLen, xtra);
#else
return SECFailure;
#endif
}
SECStatus
@ -2070,6 +2158,36 @@ ChaCha20_Xor(unsigned char *output, const unsigned char *block, unsigned int len
return (vector->p_ChaCha20_Xor)(output, block, len, k, nonce, ctr);
}
SECStatus
ChaCha20_InitContext(ChaCha20Context *ctx, const unsigned char *key,
unsigned int keyLen,
const unsigned char *nonce,
unsigned int nonceLen,
PRUint32 ctr)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_ChaCha20_InitContext)(ctx, key, keyLen, nonce, nonceLen, ctr);
}
ChaCha20Context *
ChaCha20_CreateContext(const unsigned char *key, unsigned int keyLen,
const unsigned char *nonce, unsigned int nonceLen,
PRUint32 ctr)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_ChaCha20_CreateContext)(key, keyLen, nonce, nonceLen, ctr);
}
void
ChaCha20_DestroyContext(ChaCha20Context *ctx, PRBool freeit)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
(vector->p_ChaCha20_DestroyContext)(ctx, freeit);
}
SECStatus
ChaCha20Poly1305_InitContext(ChaCha20Poly1305Context *ctx,
const unsigned char *key, unsigned int keyLen,
@ -2127,6 +2245,38 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx,
nonce, nonceLen, ad, adLen);
}
SECStatus
ChaCha20Poly1305_Encrypt(const ChaCha20Poly1305Context *ctx,
unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen,
unsigned char *tagOut)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_ChaCha20Poly1305_Encrypt)(
ctx, output, outputLen, maxOutputLen, input, inputLen,
nonce, nonceLen, ad, adLen, tagOut);
}
SECStatus
ChaCha20Poly1305_Decrypt(const ChaCha20Poly1305Context *ctx,
unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen,
unsigned char *tagIn)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_ChaCha20Poly1305_Decrypt)(
ctx, output, outputLen, maxOutputLen, input, inputLen,
nonce, nonceLen, ad, adLen, tagIn);
}
int
EC_GetPointSize(const ECParams *params)
{

View file

@ -10,7 +10,7 @@
#include "blapi.h"
#define FREEBL_VERSION 0x0316
#define FREEBL_VERSION 0x0325
struct FREEBLVectorStr {
@ -778,6 +778,59 @@ struct FREEBLVectorStr {
void (*p_CMAC_Destroy)(CMACContext *ctx, PRBool free_it);
/* Version 3.022 came to here */
SECStatus (*p_ChaCha20Poly1305_Encrypt)(
const ChaCha20Poly1305Context *ctx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen, unsigned char *tagOut);
SECStatus (*p_ChaCha20Poly1305_Decrypt)(
const ChaCha20Poly1305Context *ctx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
const unsigned char *nonce, unsigned int nonceLen,
const unsigned char *ad, unsigned int adLen, unsigned char *tagIn);
SECStatus (*p_AES_AEAD)(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
void *params, unsigned int paramsLen,
const unsigned char *aad, unsigned int aadLen);
SECStatus (*p_AESKeyWrap_EncryptKWP)(AESKeyWrapContext *cx,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen);
SECStatus (*p_AESKeyWrap_DecryptKWP)(AESKeyWrapContext *cx,
unsigned char *output,
unsigned int *outputLen,
unsigned int maxOutputLen,
const unsigned char *input,
unsigned int inputLen);
/* Version 3.023 came to here */
PRBool (*p_KEA_PrimeCheck)(SECItem *prime);
/* Version 3.024 came to here */
SECStatus (*p_ChaCha20_InitContext)(ChaCha20Context *ctx,
const unsigned char *key,
unsigned int keyLen,
const unsigned char *nonce,
unsigned int nonceLen,
PRUint32 ctr);
ChaCha20Context *(*p_ChaCha20_CreateContext)(const unsigned char *key,
unsigned int keyLen,
const unsigned char *nonce,
unsigned int nonceLen,
PRUint32 ctr);
void (*p_ChaCha20_DestroyContext)(ChaCha20Context *ctx, PRBool freeit);
/* Version 3.025 came to here */
/* Add new function pointers at the end of this struct and bump
* FREEBL_VERSION at the beginning of this file. */
@ -829,3 +882,55 @@ extern FREEBLGetVectorFn FREEBL_GetVector;
SEC_END_PROTOS
#endif
#ifdef NSS_DISABLE_DEPRECATED_SEED
typedef SECStatus (*F_SEED_InitContext)(SEEDContext *cx,
const unsigned char *key,
unsigned int keylen,
const unsigned char *iv,
int mode,
unsigned int encrypt,
unsigned int);
typedef SEEDContext *(*F_SEED_AllocateContext)(void);
typedef SEEDContext *(*F_SEED_CreateContext)(const unsigned char *key,
const unsigned char *iv,
int mode, PRBool encrypt);
typedef void (*F_SEED_DestroyContext)(SEEDContext *cx, PRBool freeit);
typedef SECStatus (*F_SEED_Encrypt)(SEEDContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
typedef SECStatus (*F_SEED_Decrypt)(SEEDContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
#endif
#ifdef NSS_DISABLE_DEPRECATED_RC2
typedef RC2Context *(*F_RC2_CreateContext)(const unsigned char *key,
unsigned int len, const unsigned char *iv,
int mode, unsigned effectiveKeyLen);
typedef void (*F_RC2_DestroyContext)(RC2Context *cx, PRBool freeit);
typedef SECStatus (*F_RC2_Encrypt)(RC2Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
typedef SECStatus (*F_RC2_Decrypt)(RC2Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen);
typedef SECStatus (*F_RC2_InitContext)(RC2Context *cx,
const unsigned char *key,
unsigned int keylen,
const unsigned char *iv,
int mode,
unsigned int effectiveKeyLen,
unsigned int);
typedef RC2Context *(*F_RC2_AllocateContext)(void);
#endif

View file

@ -123,10 +123,9 @@ CSRCS = \
cmac.c \
alghmac.c \
rawhash.c \
alg2268.c \
arcfour.c \
arcfive.c \
crypto_primitives.c \
crypto_primitives.c \
blake2b.c \
desblapi.c \
des.c \
@ -150,8 +149,8 @@ CSRCS = \
rsapkcs.c \
shvfy.c \
tlsprfalg.c \
seed.c \
jpake.c \
secmpi.c \
$(MPI_SRCS) \
$(MPCPU_SRCS) \
$(ECL_SRCS) \
@ -161,6 +160,14 @@ CSRCS = \
$(EXTRA_SRCS) \
$(NULL)
ifndef NSS_DISABLE_DEPRECATED_SEED
CSRCS += deprecated/seed.c
endif
ifndef NSS_DISABLE_DEPRECATED_RC2
CSRCS += deprecated/alg2268.c
endif
ALL_CSRCS := $(CSRCS)
ALL_HDRS = \

0
security/nss/lib/freebl/mpi/doc/build Normal file → Executable file
View file

View file

@ -198,7 +198,7 @@ L18:
mov dword ptr [8+rbx], edi
je L9
lea r10d, dword ptr [-2+rdx]
cmp dword ptr [r11+r10*8], 0
cmp qword ptr [r11+r10*8], 0
je L18
L9:
mov edx, dword ptr [8+rbx]
@ -689,7 +689,7 @@ L43:
mov dword ptr [8+rbx], edi
je L35
lea eax, dword ptr [-2+rdx]
cmp dword ptr [r11+rax*8], 0
cmp qword ptr [r11+rax*8], 0
je L43
L35:
mov r11d, dword ptr [8+rbx]
@ -2268,7 +2268,7 @@ L84:
mov dword ptr [8+rbx], edi
je L76
lea eax, dword ptr [-2+rdx]
cmp dword ptr [r11+rax*8], 0
cmp qword ptr [r11+rax*8], 0
je L84
L76:
mov edx, dword ptr [8+rbx]
@ -7830,7 +7830,7 @@ L157:
mov dword ptr [8+r13], ebx
je L149
lea r12d, dword ptr [-2+rdx]
cmp dword ptr [r9+r12*8], 0
cmp qword ptr [r9+r12*8], 0
je L157
L149:
mov r9d, dword ptr [8+r13]
@ -7990,7 +7990,7 @@ s_mp_sqr_comba_4 PROC
lea ecx, dword ptr [-1+rdx]
mov rsi, qword ptr [16+r11]
mov r10d, ecx
cmp dword ptr [rsi+r10*8], 0
cmp qword ptr [rsi+r10*8], 0
jne L166
mov edx, ecx
ALIGN 16
@ -8000,7 +8000,7 @@ L167:
je L171
dec edx
mov eax, edx
cmp dword ptr [rsi+rax*8], 0
cmp qword ptr [rsi+rax*8], 0
je L167
mov dword ptr [8+r11], ecx
mov edx, ecx
@ -8415,7 +8415,7 @@ s_mp_sqr_comba_8 PROC
lea ecx, dword ptr [-1+rdx]
mov rsi, qword ptr [16+rbp]
mov r14d, ecx
cmp dword ptr [rsi+r14*8], 0
cmp qword ptr [rsi+r14*8], 0
jne L190
mov edx, ecx
ALIGN 16
@ -8425,7 +8425,7 @@ L191:
je L195
dec edx
mov r9d, edx
cmp dword ptr [rsi+r9*8], 0
cmp qword ptr [rsi+r9*8], 0
je L191
mov dword ptr [8+rbp], ecx
mov edx, ecx
@ -9511,7 +9511,7 @@ s_mp_sqr_comba_16 PROC ; A "FRAME" function
lea ecx, dword ptr [-1+rdx]
mov rsi, qword ptr [16+r14]
mov r9d, ecx
cmp dword ptr [rsi+r9*8], 0
cmp qword ptr [rsi+r9*8], 0
jne L230
mov edx, ecx
ALIGN 16
@ -9521,7 +9521,7 @@ L231:
je L235
dec edx
mov eax, edx
cmp dword ptr [rsi+rax*8], 0
cmp qword ptr [rsi+rax*8], 0
je L231
mov dword ptr [8+r14], ecx
mov edx, ecx
@ -13023,7 +13023,7 @@ s_mp_sqr_comba_32 PROC ; A "FRAME" function
lea ecx, dword ptr [-1+rdx]
mov rsi, qword ptr [16+r14]
mov r10d, ecx
cmp dword ptr [rsi+r10*8], 0
cmp qword ptr [rsi+r10*8], 0
jne L302
mov edx, ecx
ALIGN 16
@ -13033,7 +13033,7 @@ L303:
je L307
dec edx
mov eax, edx
cmp dword ptr [rsi+rax*8], 0
cmp qword ptr [rsi+rax*8], 0
je L303
mov dword ptr [8+r14], ecx
mov edx, ecx

View file

@ -7,11 +7,10 @@
#include "mplogic.h"
#include "mpi-priv.h"
const mp_digit mp_gf2m_sqr_tb[16] =
{
0, 1, 4, 5, 16, 17, 20, 21,
64, 65, 68, 69, 80, 81, 84, 85
};
const mp_digit mp_gf2m_sqr_tb[16] = {
0, 1, 4, 5, 16, 17, 20, 21,
64, 65, 68, 69, 80, 81, 84, 85
};
/* Multiply two binary polynomials mp_digits a, b.
* Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1.

View file

@ -39,7 +39,8 @@ freebl_cpuid(unsigned long op, unsigned long *eax,
unsigned long *ebx, unsigned long *ecx,
unsigned long *edx)
{
__asm__("cpuid\n\t"
__asm__("xor %%ecx, %%ecx\n\t"
"cpuid\n\t"
: "=a"(*eax),
"=b"(*ebx),
"=c"(*ecx),
@ -726,10 +727,10 @@ s_mpi_getProcessorLineSize()
static inline void
dcbzl(char *array)
{
register char *a asm("r2") = array;
__asm__ __volatile__("dcbzl %0,0"
: "=r"(a)
: "0"(a));
__asm__("dcbzl %0, %1"
: /*no result*/
: "b%"(array), "r"(0)
: "memory");
}
#define PPC_DO_ALIGN(x, y) ((char *)((((long long)(x)) + ((y)-1)) & ~((y)-1)))

View file

@ -157,7 +157,7 @@ mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c);
mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c);
#ifdef NSS_USE_COMBA
PR_STATIC_ASSERT(sizeof(mp_digit) == 8);
#define IS_POWER_OF_2(a) ((a) && !((a) & ((a)-1)))
void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C);
@ -204,6 +204,9 @@ void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
mp_size a_len, mp_digit b,
mp_digit *c);
void MPI_ASM_DECL s_mpv_mul_d_add_propCT(const mp_digit *a,
mp_size a_len, mp_digit b,
mp_digit *c, mp_size c_len);
void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
mp_size a_len,
mp_digit *sqrs);

View file

@ -9,9 +9,8 @@
#include "mpi-priv.h"
#include "mplogic.h"
#if defined(OSF1)
#include <c_asm.h>
#endif
#include <assert.h>
#if defined(__arm__) && \
((defined(__thumb__) && !defined(__thumb2__)) || defined(__ARM_ARCH_3__))
@ -805,15 +804,18 @@ CLEANUP:
/* }}} */
/* {{{ mp_mul(a, b, c) */
/* {{{ s_mp_mulg(a, b, c) */
/*
mp_mul(a, b, c)
s_mp_mulg(a, b, c)
Compute c = a * b. All parameters may be identical.
Compute c = a * b. All parameters may be identical. if constantTime is set,
then the operations are done in constant time. The original is mostly
constant time as long as s_mpv_mul_d_add() is constant time. This is true
of the x86 assembler, as well as the current c code.
*/
mp_err
mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
s_mp_mulg(const mp_int *a, const mp_int *b, mp_int *c, int constantTime)
{
mp_digit *pb;
mp_int tmp;
@ -849,7 +851,14 @@ mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
goto CLEANUP;
#ifdef NSS_USE_COMBA
if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
/* comba isn't constant time because it clamps! If we cared
* (we needed a constant time version of multiply that was 'faster'
* we could easily pass constantTime down to the comba code and
* get it to skip the clamp... but here are assembler versions
* which add comba to platforms that can't compile the normal
* comba's imbedded assembler which would also need to change, so
* for now we just skip comba when we are running constant time. */
if (!constantTime && (MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
if (MP_USED(a) == 4) {
s_mp_mul_comba_4(a, b, c);
goto CLEANUP;
@ -879,13 +888,15 @@ mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
mp_digit b_i = *pb++;
/* Inner product: Digits of a */
if (b_i)
if (constantTime || b_i)
s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
else
MP_DIGIT(c, ib + useda) = b_i;
}
s_mp_clamp(c);
if (!constantTime) {
s_mp_clamp(c);
}
if (SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
SIGN(c) = ZPOS;
@ -895,10 +906,54 @@ mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
CLEANUP:
mp_clear(&tmp);
return res;
} /* end smp_mulg() */
/* }}} */
/* {{{ mp_mul(a, b, c) */
/*
mp_mul(a, b, c)
Compute c = a * b. All parameters may be identical.
*/
mp_err
mp_mul(const mp_int *a, const mp_int *b, mp_int *c)
{
return s_mp_mulg(a, b, c, 0);
} /* end mp_mul() */
/* }}} */
/* {{{ mp_mulCT(a, b, c) */
/*
mp_mulCT(a, b, c)
Compute c = a * b. In constant time. Parameters may not be identical.
NOTE: a and b may be modified.
*/
mp_err
mp_mulCT(mp_int *a, mp_int *b, mp_int *c, mp_size setSize)
{
mp_err res;
/* make the multiply values fixed length so multiply
* doesn't leak the length. at this point all the
* values are blinded, but once we finish we want the
* output size to be hidden (so no clamping the out put) */
MP_CHECKOK(s_mp_pad(a, setSize));
MP_CHECKOK(s_mp_pad(b, setSize));
MP_CHECKOK(s_mp_pad(c, 2 * setSize));
MP_CHECKOK(s_mp_mulg(a, b, c, 1));
CLEANUP:
return res;
} /* end mp_mulCT() */
/* }}} */
/* {{{ mp_sqr(a, sqr) */
#if MP_SQUARE
@ -1271,6 +1326,138 @@ mp_mod(const mp_int *a, const mp_int *m, mp_int *c)
/* }}} */
/* {{{ s_mp_subCT_d(a, b, borrow, c) */
/*
s_mp_subCT_d(a, b, borrow, c)
Compute c = (a -b) - subtract in constant time. returns borrow
*/
mp_digit
s_mp_subCT_d(mp_digit a, mp_digit b, mp_digit borrow, mp_digit *ret)
{
*ret = a - b - borrow;
return MP_CT_LTU(a, *ret) | (MP_CT_EQ(a, *ret) & borrow);
} /* s_mp_subCT_d() */
/* }}} */
/* {{{ mp_subCT(a, b, ret, borrow) */
/* return ret= a - b and borrow in borrow. done in constant time.
* b could be modified.
*/
mp_err
mp_subCT(const mp_int *a, mp_int *b, mp_int *ret, mp_digit *borrow)
{
mp_size used_a = MP_USED(a);
mp_size i;
mp_err res;
MP_CHECKOK(s_mp_pad(b, used_a));
MP_CHECKOK(s_mp_pad(ret, used_a));
*borrow = 0;
for (i = 0; i < used_a; i++) {
*borrow = s_mp_subCT_d(MP_DIGIT(a, i), MP_DIGIT(b, i), *borrow,
&MP_DIGIT(ret, i));
}
res = MP_OKAY;
CLEANUP:
return res;
} /* end mp_subCT() */
/* }}} */
/* {{{ mp_selectCT(cond, a, b, ret) */
/*
* return ret= cond ? a : b; cond should be either 0 or 1
*/
mp_err
mp_selectCT(mp_digit cond, const mp_int *a, const mp_int *b, mp_int *ret)
{
mp_size used_a = MP_USED(a);
mp_err res;
mp_size i;
cond *= MP_DIGIT_MAX;
/* we currently require these to be equal on input,
* we could use pad to extend one of them, but that might
* leak data as it wouldn't be constant time */
if (used_a != MP_USED(b)) {
return MP_BADARG;
}
MP_CHECKOK(s_mp_pad(ret, used_a));
for (i = 0; i < used_a; i++) {
MP_DIGIT(ret, i) = MP_CT_SEL_DIGIT(cond, MP_DIGIT(a, i), MP_DIGIT(b, i));
}
res = MP_OKAY;
CLEANUP:
return res;
} /* end mp_selectCT() */
/* {{{ mp_reduceCT(a, m, c) */
/*
mp_reduceCT(a, m, c)
Compute c = aR^-1 (mod m) in constant time.
input should be in montgomery form. If input is the
result of a montgomery multiply then out put will be
in mongomery form.
Result will be reduced to MP_USED(m), but not be
clamped.
*/
mp_err
mp_reduceCT(const mp_int *a, const mp_int *m, mp_digit n0i, mp_int *c)
{
mp_size used_m = MP_USED(m);
mp_size used_c = used_m * 2 + 1;
mp_digit *m_digits, *c_digits;
mp_size i;
mp_digit borrow, carry;
mp_err res;
mp_int sub;
MP_DIGITS(&sub) = 0;
MP_CHECKOK(mp_init_size(&sub, used_m));
if (a != c) {
MP_CHECKOK(mp_copy(a, c));
}
MP_CHECKOK(s_mp_pad(c, used_c));
m_digits = MP_DIGITS(m);
c_digits = MP_DIGITS(c);
for (i = 0; i < used_m; i++) {
mp_digit m_i = MP_DIGIT(c, i) * n0i;
s_mpv_mul_d_add_propCT(m_digits, used_m, m_i, c_digits++, used_c--);
}
s_mp_rshd(c, used_m);
/* MP_USED(c) should be used_m+1 with the high word being any carry
* from the previous multiply, save that carry and drop the high
* word for the substraction below */
carry = MP_DIGIT(c, used_m);
MP_DIGIT(c, used_m) = 0;
MP_USED(c) = used_m;
/* mp_subCT wants c and m to be the same size, we've already
* guarrenteed that in the previous statement, so mp_subCT won't actually
* modify m, so it's safe to recast */
MP_CHECKOK(mp_subCT(c, (mp_int *)m, &sub, &borrow));
/* we return c-m if c >= m no borrow or there was a borrow and a carry */
MP_CHECKOK(mp_selectCT(borrow ^ carry, c, &sub, c));
res = MP_OKAY;
CLEANUP:
mp_clear(&sub);
return res;
} /* end mp_reduceCT() */
/* }}} */
/* {{{ mp_mod_d(a, d, c) */
/*
@ -1387,6 +1574,37 @@ mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
/* }}} */
/* {{{ mp_mulmontmodCT(a, b, m, c) */
/*
mp_mulmontmodCT(a, b, m, c)
Compute c = (a * b) mod m in constant time wrt a and b. either a or b
should be in montgomery form and the output is native. If both a and b
are in montgomery form, then the output will also be in montgomery form
and can be recovered with an mp_reduceCT call.
NOTE: a and b may be modified.
*/
mp_err
mp_mulmontmodCT(mp_int *a, mp_int *b, const mp_int *m, mp_digit n0i,
mp_int *c)
{
mp_err res;
ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
if ((res = mp_mulCT(a, b, c, MP_USED(m))) != MP_OKAY)
return res;
if ((res = mp_reduceCT(c, m, n0i, c)) != MP_OKAY)
return res;
return MP_OKAY;
}
/* }}} */
/* {{{ mp_sqrmod(a, m, c) */
#if MP_SQUARE
@ -2523,12 +2741,6 @@ mp_read_raw(mp_int *mp, char *str, int len)
mp_zero(mp);
/* Get sign from first byte */
if (ustr[0])
SIGN(mp) = NEG;
else
SIGN(mp) = ZPOS;
/* Read the rest of the digits */
for (ix = 1; ix < len; ix++) {
if ((res = mp_mul_d(mp, 256, mp)) != MP_OKAY)
@ -2537,6 +2749,12 @@ mp_read_raw(mp_int *mp, char *str, int len)
return res;
}
/* Get sign from first byte */
if (ustr[0])
SIGN(mp) = NEG;
else
SIGN(mp) = ZPOS;
return MP_OKAY;
} /* end mp_read_raw() */
@ -2693,7 +2911,7 @@ mp_radix_size(mp_int *mp, int radix)
bits = USED(mp) * DIGIT_BIT - 1;
return s_mp_outlen(bits, radix);
return SIGN(mp) + s_mp_outlen(bits, radix);
} /* end mp_radix_size() */
@ -3248,7 +3466,8 @@ CLEANUP:
/* {{{ s_mp_add_d(mp, d) */
/* Add d to |mp| in place */
mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */
mp_err
s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */
{
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
mp_word w, k = 0;
@ -3305,7 +3524,8 @@ CLEANUP:
/* {{{ s_mp_sub_d(mp, d) */
/* Subtract d from |mp| in place, assumes |mp| > d */
mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */
mp_err
s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */
{
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
mp_word w, b = 0;
@ -3512,7 +3732,8 @@ CLEANUP:
/* {{{ s_mp_add(a, b) */
/* Compute a = |a| + |b| */
mp_err s_mp_add(mp_int *a, const mp_int *b) /* magnitude addition */
mp_err
s_mp_add(mp_int *a, const mp_int *b) /* magnitude addition */
{
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
mp_word w = 0;
@ -3775,7 +3996,8 @@ s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset)
/* {{{ s_mp_sub(a, b) */
/* Compute a = |a| - |b|, assumes |a| >= |b| */
mp_err s_mp_sub(mp_int *a, const mp_int *b) /* magnitude subtract */
mp_err
s_mp_sub(mp_int *a, const mp_int *b) /* magnitude subtract */
{
mp_digit *pa, *pb, *limit;
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
@ -3930,12 +4152,6 @@ s_mp_mul(mp_int *a, const mp_int *b)
Plo = (mp_digit)product; \
Phi = (mp_digit)(product >> MP_DIGIT_BIT); \
}
#elif defined(OSF1)
#define MP_MUL_DxD(a, b, Phi, Plo) \
{ \
Plo = asm("mulq %a0, %a1, %v0", a, b); \
Phi = asm("umulh %a0, %a1, %v0", a, b); \
}
#else
#define MP_MUL_DxD(a, b, Phi, Plo) \
{ \
@ -3946,15 +4162,63 @@ s_mp_mul(mp_int *a, const mp_int *b)
a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
a1b0 += a0b1; \
Phi += a1b0 >> MP_HALF_DIGIT_BIT; \
if (a1b0 < a0b1) \
Phi += MP_HALF_RADIX; \
Phi += (MP_CT_LTU(a1b0, a0b1)) << MP_HALF_DIGIT_BIT; \
a1b0 <<= MP_HALF_DIGIT_BIT; \
Plo += a1b0; \
if (Plo < a1b0) \
++Phi; \
Phi += MP_CT_LTU(Plo, a1b0); \
}
#endif
/* Constant time version of s_mpv_mul_d_add_prop.
* Presently, this is only used by the Constant time Montgomery arithmetic code. */
/* c += a * b */
void
s_mpv_mul_d_add_propCT(const mp_digit *a, mp_size a_len, mp_digit b,
mp_digit *c, mp_size c_len)
{
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
mp_digit d = 0;
c_len -= a_len;
/* Inner product: Digits of a */
while (a_len--) {
mp_word w = ((mp_word)b * *a++) + *c + d;
*c++ = ACCUM(w);
d = CARRYOUT(w);
}
/* propagate the carry to the end, even if carry is zero */
while (c_len--) {
mp_word w = (mp_word)*c + d;
*c++ = ACCUM(w);
d = CARRYOUT(w);
}
#else
mp_digit carry = 0;
c_len -= a_len;
while (a_len--) {
mp_digit a_i = *a++;
mp_digit a0b0, a1b1;
MP_MUL_DxD(a_i, b, a1b1, a0b0);
a0b0 += carry;
a1b1 += MP_CT_LTU(a0b0, carry);
a0b0 += a_i = *c;
a1b1 += MP_CT_LTU(a0b0, a_i);
*c++ = a0b0;
carry = a1b1;
}
/* propagate the carry to the end, even if carry is zero */
while (c_len--) {
mp_digit c_i = *c;
carry += c_i;
*c++ = carry;
carry = MP_CT_LTU(carry, c_i);
}
#endif
}
#if !defined(MP_ASSEMBLY_MULTIPLY)
/* c = a * b */
void
@ -3979,8 +4243,7 @@ s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
MP_MUL_DxD(a_i, b, a1b1, a0b0);
a0b0 += carry;
if (a0b0 < carry)
++a1b1;
a1b1 += MP_CT_LTU(a0b0, carry);
*c++ = a0b0;
carry = a1b1;
}
@ -4012,11 +4275,9 @@ s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
MP_MUL_DxD(a_i, b, a1b1, a0b0);
a0b0 += carry;
if (a0b0 < carry)
++a1b1;
a1b1 += MP_CT_LTU(a0b0, carry);
a0b0 += a_i = *c;
if (a0b0 < a_i)
++a1b1;
a1b1 += MP_CT_LTU(a0b0, a_i);
*c++ = a0b0;
carry = a1b1;
}
@ -4081,12 +4342,6 @@ s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
Plo = (mp_digit)square; \
Phi = (mp_digit)(square >> MP_DIGIT_BIT); \
}
#elif defined(OSF1)
#define MP_SQR_D(a, Phi, Plo) \
{ \
Plo = asm("mulq %a0, %a0, %v0", a); \
Phi = asm("umulh %a0, %a0, %v0", a); \
}
#else
#define MP_SQR_D(a, Phi, Plo) \
{ \
@ -4253,9 +4508,10 @@ s_mp_sqr(mp_int *a)
Compute a = a / b and b = a mod b. Assumes b > a.
*/
mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
mp_int *div, /* i: divisor */
mp_int *quot) /* i: 0; o: quotient */
mp_err
s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
mp_int *div, /* i: divisor */
mp_int *quot) /* i: 0; o: quotient */
{
mp_int part, t;
mp_digit q_msd;

View file

@ -64,7 +64,7 @@ typedef int mp_err;
/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */
#elif defined(ULONG_LONG_MAX) /* HPUX */
#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
#elif defined(ULONGLONG_MAX) /* IRIX, AIX */
#elif defined(ULONGLONG_MAX) /* AIX */
#define MP_ULONG_LONG_MAX ULONGLONG_MAX
#endif
@ -150,6 +150,38 @@ typedef int mp_sword;
/* This defines the maximum I/O base (minimum is 2) */
#define MP_MAX_RADIX 64
/* Constant Time Macros on mp_digits */
#define MP_CT_HIGH_TO_LOW(x) ((mp_digit)((mp_digit)(x) >> (MP_DIGIT_BIT - 1)))
#define MP_CT_TRUE ((mp_digit)1)
#define MP_CT_FALSE ((mp_digit)0)
/* basic zero and non zero tests */
#define MP_CT_NOT_ZERO(x) (MP_CT_HIGH_TO_LOW(((x) | (((mp_digit)0) - (x)))))
#define MP_CT_ZERO(x) (MP_CT_TRUE ^ MP_CT_HIGH_TO_LOW(((x) | (((mp_digit)0) - (x)))))
/* basic constant-time helper macro for equalities and inequalities.
* The inequalities will produce incorrect results if
* abs(a-b) >= MP_DIGIT_SIZE/2. This can be avoided if unsigned values stay
* within the range 0-MP_DIGIT_MAX/2. */
#define MP_CT_EQ(a, b) MP_CT_ZERO(((a) ^ (b)))
#define MP_CT_NE(a, b) MP_CT_NOT_ZERO(((a) ^ (b)))
#define MP_CT_GT(a, b) MP_CT_HIGH_TO_LOW((b) - (a))
#define MP_CT_LT(a, b) MP_CT_HIGH_TO_LOW((a) - (b))
#define MP_CT_GE(a, b) (MP_CT_TRUE ^ MP_CT_LT(a, b))
#define MP_CT_LE(a, b) (MP_CT_TRUE ^ MP_CT_GT(a, b))
/* use constant time result to select a boolean value
* or an mp digit depending on the args */
#define MP_CT_SEL(m, l, r) ((r) ^ ((m) & ((r) ^ (l))))
#define MP_CT_SELB(m, l, r) MP_CT_SEL(m, l, r) /* mask, l and r are booleans */
#define MP_CT_SEL_DIGIT(m, l, r) MP_CT_SEL(m, l, r) /*mask, l, and r are mp_digit */
/* full inequalities that work with full mp_digit values */
#define MP_CT_OVERFLOW(a, b, c, d) \
MP_CT_SELB(MP_CT_HIGH_TO_LOW((a) ^ (b)), \
(MP_CT_HIGH_TO_LOW(d)), c)
#define MP_CT_LTU(a, b) MP_CT_OVERFLOW(a, b, MP_CT_LT(a, b), b)
typedef struct {
mp_sign sign; /* sign of this quantity */
mp_size alloc; /* how many digits allocated */
@ -190,7 +222,9 @@ mp_err mp_neg(const mp_int *a, mp_int *b);
/* Full arithmetic */
mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
mp_err mp_subCT(const mp_int *a, mp_int *b, mp_int *c, mp_digit *borrow);
mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
mp_err mp_mulCT(mp_int *a, mp_int *b, mp_int *c, mp_size setSize);
#if MP_SQUARE
mp_err mp_sqr(const mp_int *a, mp_int *b);
#else
@ -217,6 +251,12 @@ mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
#endif /* MP_MODARITH */
/* montgomery math */
mp_err mp_to_mont(const mp_int *x, const mp_int *N, mp_int *xMont);
mp_digit mp_calculate_mont_n0i(const mp_int *N);
mp_err mp_reduceCT(const mp_int *a, const mp_int *m, mp_digit n0i, mp_int *ct);
mp_err mp_mulmontmodCT(mp_int *a, mp_int *b, const mp_int *m, mp_digit n0i, mp_int *c);
/* Comparisons */
int mp_cmp_z(const mp_int *a);
int mp_cmp_d(const mp_int *a, mp_digit d);
@ -224,6 +264,7 @@ int mp_cmp(const mp_int *a, const mp_int *b);
int mp_cmp_mag(const mp_int *a, const mp_int *b);
int mp_isodd(const mp_int *a);
int mp_iseven(const mp_int *a);
mp_err mp_selectCT(mp_digit cond, const mp_int *a, const mp_int *b, mp_int *ret);
/* Number theoretic */
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);

View file

@ -18,7 +18,15 @@
# s_mpv_mul_set_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
#
.text; .align 16; .globl s_mpv_mul_set_vec64; .type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
.text; .align 16; .globl s_mpv_mul_set_vec64;
#ifdef DARWIN
#define s_mpv_mul_set_vec64 _s_mpv_mul_set_vec64
.private_extern s_mpv_mul_set_vec64
s_mpv_mul_set_vec64:
#else
.type s_mpv_mul_set_vec64, @function; s_mpv_mul_set_vec64:
#endif
xorq %rax, %rax # if (len == 0) return (0)
testq %rdx, %rdx
@ -169,7 +177,9 @@
movq %r9, %rax
ret
#ifndef DARWIN
.size s_mpv_mul_set_vec64, .-s_mpv_mul_set_vec64
#endif
# ------------------------------------------------------------------------
#
@ -186,7 +196,15 @@
# s_mpv_mul_add_vec64(uint64_t *r, uint64_t *a, int len, uint64_t digit)
#
.text; .align 16; .globl s_mpv_mul_add_vec64; .type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
.text; .align 16; .globl s_mpv_mul_add_vec64;
#ifdef DARWIN
#define s_mpv_mul_add_vec64 _s_mpv_mul_add_vec64
.private_extern s_mpv_mul_add_vec64
s_mpv_mul_add_vec64:
#else
.type s_mpv_mul_add_vec64, @function; s_mpv_mul_add_vec64:
#endif
xorq %rax, %rax # if (len == 0) return (0)
testq %rdx, %rdx
@ -381,9 +399,11 @@
.L27:
movq %r9, %rax
ret
#ifndef DARWIN
.size s_mpv_mul_add_vec64, .-s_mpv_mul_add_vec64
# Magic indicating no need for an executable stack
.section .note.GNU-stack, "", @progbits
.previous
#endif

View file

@ -222,10 +222,9 @@ mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
/* {{{ mpl_num_set(a, num) */
mp_err
mpl_num_set(mp_int *a, int *num)
mpl_num_set(mp_int *a, unsigned int *num)
{
unsigned int ix;
int db, nset = 0;
unsigned int ix, db, nset = 0;
mp_digit cur;
unsigned char reg;
@ -253,10 +252,9 @@ mpl_num_set(mp_int *a, int *num)
/* {{{ mpl_num_clear(a, num) */
mp_err
mpl_num_clear(mp_int *a, int *num)
mpl_num_clear(mp_int *a, unsigned int *num)
{
unsigned int ix;
int db, nset = 0;
unsigned int ix, db, nset = 0;
mp_digit cur;
unsigned char reg;

View file

@ -11,6 +11,7 @@
#define _H_MPLOGIC_
#include "mpi.h"
SEC_BEGIN_PROTOS
/*
The logical operations treat an mp_int as if it were a bit vector,
@ -38,9 +39,9 @@ mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d); /* left shift */
/* Bit count and parity */
mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */
mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */
mp_err mpl_parity(mp_int *a); /* determine parity */
mp_err mpl_num_set(mp_int *a, unsigned int *num); /* count set bits */
mp_err mpl_num_clear(mp_int *a, unsigned int *num); /* count clear bits */
mp_err mpl_parity(mp_int *a); /* determine parity */
/* Get & Set the value of a bit */
@ -49,4 +50,6 @@ mp_err mpl_get_bit(const mp_int *a, mp_size bitNum);
mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits);
mp_size mpl_significant_bits(const mp_int *a);
SEC_END_PROTOS
#endif /* end _H_MPLOGIC_ */

View file

@ -129,20 +129,27 @@ CLEANUP:
}
#endif
STATIC
mp_err
s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont)
mp_to_mont(const mp_int *x, const mp_int *N, mp_int *xMont)
{
mp_err res;
/* xMont = x * R mod N where N is modulus */
MP_CHECKOK(mp_copy(x, xMont));
MP_CHECKOK(s_mp_lshd(xMont, MP_USED(&mmm->N))); /* xMont = x << b */
MP_CHECKOK(mp_div(xMont, &mmm->N, 0, xMont)); /* mod N */
if (x != xMont) {
MP_CHECKOK(mp_copy(x, xMont));
}
MP_CHECKOK(s_mp_lshd(xMont, MP_USED(N))); /* xMont = x << b */
MP_CHECKOK(mp_div(xMont, N, 0, xMont)); /* mod N */
CLEANUP:
return res;
}
mp_digit
mp_calculate_mont_n0i(const mp_int *N)
{
return 0 - s_mp_invmod_radix(MP_DIGIT(N, 0));
}
#ifdef MP_USING_MONT_MULF
/* the floating point multiply is already cache safe,
@ -198,7 +205,7 @@ mp_exptmod_f(const mp_int *montBase,
MP_CHECKOK(mp_init_size(&accum1, 3 * nLen + 2));
mp_set(&accum1, 1);
MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
MP_CHECKOK(s_mp_pad(&accum1, nLen));
oddPowSize = 2 * nLen + 1;
@ -478,7 +485,7 @@ mp_exptmod_i(const mp_int *montBase,
/* set accumulator to montgomery residue of 1 */
mp_set(&accum1, 1);
MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
pa1 = &accum1;
pa2 = &accum2;
@ -723,10 +730,11 @@ mp_set_safe_modexp(int value)
* mp_ints that use less than nDigits digits are logically padded with zeros
* while being stored in the weaved array.
*/
mp_err mpi_to_weave(const mp_int *bignums,
mp_digit *weaved,
mp_size nDigits, /* in each mp_int of input */
mp_size nBignums) /* in the entire source array */
mp_err
mpi_to_weave(const mp_int *bignums,
mp_digit *weaved,
mp_size nDigits, /* in each mp_int of input */
mp_size nBignums) /* in the entire source array */
{
mp_size i;
mp_digit *endDest = weaved + (nDigits * nBignums);
@ -765,11 +773,12 @@ mp_err mpi_to_weave(const mp_int *bignums,
* Every read accesses every element of the weaved array, in order to
* avoid timing attacks based on patterns of memory accesses.
*/
mp_err weave_to_mpi(mp_int *a, /* out, result */
const mp_digit *weaved, /* in, byte matrix */
mp_size index, /* which column to read */
mp_size nDigits, /* number of mp_digits in each bignum */
mp_size nBignums) /* width of the matrix */
mp_err
weave_to_mpi(mp_int *a, /* out, result */
const mp_digit *weaved, /* in, byte matrix */
mp_size index, /* which column to read */
mp_size nDigits, /* number of mp_digits in each bignum */
mp_size nBignums) /* width of the matrix */
{
/* these are indices, but need to be the same size as mp_digit
* because of the CONST_TIME operations */
@ -865,7 +874,7 @@ mp_exptmod_safe_i(const mp_int *montBase,
MP_CHECKOK(mp_init_size(&accum[2], 3 * nLen + 2));
MP_CHECKOK(mp_init_size(&accum[3], 3 * nLen + 2));
mp_set(&accum[0], 1);
MP_CHECKOK(s_mp_to_mont(&accum[0], mmm, &accum[0]));
MP_CHECKOK(mp_to_mont(&accum[0], &(mmm->N), &accum[0]));
MP_CHECKOK(mp_copy(montBase, &accum[1]));
SQR(montBase, &accum[2]);
MUL_NOWEAVE(montBase, &accum[2], &accum[3]);
@ -884,7 +893,7 @@ mp_exptmod_safe_i(const mp_int *montBase,
} else {
if (first_window == 0) {
mp_set(&accum1, 1);
MP_CHECKOK(s_mp_to_mont(&accum1, mmm, &accum1));
MP_CHECKOK(mp_to_mont(&accum1, &(mmm->N), &accum1));
} else {
/* assert first_window == 1? */
MP_CHECKOK(mp_copy(montBase, &accum1));
@ -1006,7 +1015,11 @@ CLEANUP:
mp_clear(&accum[2]);
mp_clear(&accum[3]);
mp_clear(&tmp);
/* PORT_Memset(powers,0,num_powers*nLen*sizeof(mp_digit)); */
/* zero required by FIPS here, can't use PORT_ZFree
* because mpi doesn't link with util */
if (powers) {
PORT_Memset(powers, 0, num_powers * sizeof(mp_digit));
}
free(powersArray);
return res;
}
@ -1051,9 +1064,9 @@ mp_exptmod(const mp_int *inBase, const mp_int *exponent,
/* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
** where n0 = least significant mp_digit of N, the modulus.
*/
mmm.n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(modulus, 0));
mmm.n0prime = mp_calculate_mont_n0i(modulus);
MP_CHECKOK(s_mp_to_mont(base, &mmm, &montBase));
MP_CHECKOK(mp_to_mont(base, modulus, &montBase));
bits_in_exponent = mpl_significant_bits(exponent);
#ifdef MP_USING_CACHE_SAFE_MOD_EXP

View file

@ -126,6 +126,8 @@ mpp_random(mp_int *a)
/* }}} */
static mpp_random_fn mpp_random_insecure = &mpp_random;
/* {{{ mpp_random_size(a, prec) */
mp_err
@ -138,7 +140,7 @@ mpp_random_size(mp_int *a, mp_size prec)
if ((res = s_mp_pad(a, prec)) != MP_OKAY)
return res;
return mpp_random(a);
return (*mpp_random_insecure)(a);
} /* end mpp_random_size() */
@ -271,6 +273,12 @@ mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes)
mp_err
mpp_pprime(mp_int *a, int nt)
{
return mpp_pprime_ext_random(a, nt, mpp_random_insecure);
}
mp_err
mpp_pprime_ext_random(mp_int *a, int nt, mpp_random_fn random)
{
mp_err res;
mp_int x, amo, m, z; /* "amo" = "a minus one" */
@ -306,7 +314,7 @@ mpp_pprime(mp_int *a, int nt)
/* Choose a random value for 1 < x < a */
MP_CHECKOK(s_mp_pad(&x, USED(a)));
mpp_random(&x);
MP_CHECKOK((*random)(&x));
MP_CHECKOK(mp_mod(&x, a, &x));
if (mp_cmp_d(&x, 1) <= 0) {
iter--; /* don't count this iteration */
@ -403,6 +411,12 @@ mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
mp_err
mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong)
{
return mpp_make_prime_ext_random(start, nBits, strong, mpp_random_insecure);
}
mp_err
mpp_make_prime_ext_random(mp_int *start, mp_size nBits, mp_size strong, mpp_random_fn random)
{
mp_digit np;
mp_err res;
@ -490,7 +504,7 @@ mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong)
FPUTC('+', stderr);
/* If that passed, run some Miller-Rabin tests */
res = mpp_pprime(&trial, num_tests);
res = mpp_pprime_ext_random(&trial, num_tests, random);
if (res != MP_OKAY) {
if (res == MP_NO)
continue; /* was composite */
@ -528,7 +542,7 @@ mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong)
}
/* And test with Miller-Rabin, as with its parent ... */
res = mpp_pprime(&q, num_tests);
res = mpp_pprime_ext_random(&q, num_tests, random);
if (res != MP_YES) {
mp_clear(&q);
if (res == MP_NO)

View file

@ -26,6 +26,9 @@ mp_err mpp_divis_d(mp_int *a, mp_digit d);
mp_err mpp_random(mp_int *a);
mp_err mpp_random_size(mp_int *a, mp_size prec);
/* Type for a pointer to a user-provided mpp_random implementation */
typedef mp_err (*mpp_random_fn)(mp_int *);
/* Pseudo-primality testing */
mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which);
mp_err mpp_divis_primes(mp_int *a, mp_digit *np);
@ -36,6 +39,10 @@ mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
unsigned char *sieve, mp_size nSieve);
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong);
/* Pseudo-primality tests using a user-provided mpp_random implementation */
mp_err mpp_pprime_ext_random(mp_int *a, int nt, mpp_random_fn random);
mp_err mpp_make_prime_ext_random(mp_int *start, mp_size nBits, mp_size strong, mpp_random_fn random);
SEC_END_PROTOS
#endif /* end _H_MP_PRIME_ */

View file

@ -836,6 +836,6 @@ const mp_digit prime_tab[] = {
0xFE95, 0xFE9B, 0xFE9F, 0xFEB3, 0xFEBD, 0xFED7, 0xFEE9, 0xFEF3,
0xFEF5, 0xFF07, 0xFF0D, 0xFF1D, 0xFF2B, 0xFF2F, 0xFF49, 0xFF4D,
0xFF5B, 0xFF65, 0xFF71, 0xFF7F, 0xFF85, 0xFF8B, 0xFF8F, 0xFF9D,
0xFFA7, 0xFFA9, 0xFFC7, 0xFFD9, 0xFFEF, 0xFFF1,
0xFFA7, 0xFFA9, 0xFFC7, 0xFFD9, 0xFFEF, 0xFFF1
#endif
};

View file

@ -6,6 +6,7 @@
#include "stubs.h"
#endif
#include "prtypes.h"
#include "prenv.h"
#include "secerr.h"
#include "blapi.h"
#include "hasht.h"
@ -30,6 +31,12 @@ nsslow_GetFIPSEnabled(void)
FILE *f;
char d;
size_t size;
const char *env;
env = PR_GetEnvSecure("NSS_FIPS");
if (env && (*env == 'y' || *env == 'f' || *env == '1' || *env == 't')) {
return 1;
}
f = fopen("/proc/sys/crypto/fips_enabled", "r");
if (!f)
@ -60,7 +67,7 @@ NSSLOW_Init(void)
/* make sure the FIPS product is installed if we are trying to
* go into FIPS mode */
if (nsslow_GetFIPSEnabled()) {
if (BL_FIPSEntryOK(PR_TRUE) != SECSuccess) {
if (BL_FIPSEntryOK(PR_TRUE, PR_FALSE) != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
post_failed = PR_TRUE;
return NULL;

View file

@ -0,0 +1,31 @@
/* 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 PPC_CRYPTO_H
#define PPC_CRYPTO_H 1
#if defined(__powerpc64__) && defined(__ALTIVEC__) && \
!defined(NSS_DISABLE_ALTIVEC)
#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 8 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__ >= 8)) && \
defined(IS_LITTLE_ENDIAN) && defined(__VSX__)
#define USE_PPC_CRYPTO
#endif
#endif /* defined(__powerpc64__) && !defined(NSS_DISABLE_ALTIVEC) && defined(__ALTIVEC__) */
#endif

View file

@ -0,0 +1,458 @@
/* 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/. */
/* Copyright(c) 2013, Intel Corp. */
/* Wrapper functions for PowerPC optimized implementation of AES-GCM */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "blapii.h"
#include "blapit.h"
#include "gcm.h"
#include "ctr.h"
#include "secerr.h"
#include "prtypes.h"
#include "pkcs11t.h"
#include <limits.h>
#include <stdio.h>
#include "ppc-gcm.h"
#include "rijndael.h"
struct ppc_AES_GCMContextStr {
unsigned char Htbl[8 * AES_BLOCK_SIZE];
unsigned char X0[AES_BLOCK_SIZE];
unsigned char T[AES_BLOCK_SIZE];
unsigned char CTR[AES_BLOCK_SIZE];
AESContext *aes_context;
unsigned long tagBits;
unsigned long Alen;
unsigned long Mlen;
freeblCipherFunc cipher;
PRBool ctr_context_init;
gcmIVContext gcm_iv;
};
SECStatus ppc_aes_gcmInitCounter(ppc_AES_GCMContext *gcm,
const unsigned char *iv,
unsigned long ivLen, unsigned long tagBits,
const unsigned char *aad, unsigned long aadLen);
ppc_AES_GCMContext *
ppc_AES_GCM_CreateContext(void *context,
freeblCipherFunc cipher,
const unsigned char *params)
{
ppc_AES_GCMContext *gcm = NULL;
AESContext *aes = (AESContext *)context;
const CK_NSS_GCM_PARAMS *gcmParams = (const CK_NSS_GCM_PARAMS *)params;
SECStatus rv;
gcm = PORT_ZNew(ppc_AES_GCMContext);
if (gcm == NULL) {
return NULL;
}
/* initialize context fields */
gcm->aes_context = aes;
gcm->cipher = cipher;
gcm->Alen = 0;
gcm->Mlen = 0;
gcm->ctr_context_init = PR_FALSE;
/* first prepare H and its derivatives for ghash */
ppc_aes_gcmINIT(gcm->Htbl, aes->k.expandedKey, aes->Nr);
gcm_InitIVContext(&gcm->gcm_iv);
/* if gcmParams is NULL, then we are creating an PKCS #11 MESSAGE
* style context, in which we initialize the key once, then do separate
* iv/aad's for each message. If we are doing that kind of operation,
* we've finished with init here. We'll init the Counter in each AEAD
* call */
if (gcmParams == NULL) {
return gcm;
}
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv,
gcmParams->ulIvLen, gcmParams->ulTagBits,
gcmParams->pAAD, gcmParams->ulAADLen);
if (rv != SECSuccess) {
PORT_Free(gcm);
return NULL;
}
gcm->ctr_context_init = PR_TRUE;
return gcm;
}
SECStatus
ppc_aes_gcmInitCounter(ppc_AES_GCMContext *gcm,
const unsigned char *iv, unsigned long ivLen,
unsigned long tagBits,
const unsigned char *aad, unsigned long aadLen)
{
unsigned int j;
SECStatus rv;
if (ivLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (tagBits != 128 && tagBits != 120 && tagBits != 112 &&
tagBits != 104 && tagBits != 96 && tagBits != 64 &&
tagBits != 32) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
gcm->tagBits = tagBits;
/* reset the aad and message length counters */
gcm->Alen = 0;
gcm->Mlen = 0;
/* Initial TAG value is zero */
PORT_Memset(gcm->T, 0, AES_BLOCK_SIZE);
PORT_Memset(gcm->X0, 0, AES_BLOCK_SIZE);
/* Init the counter */
if (ivLen == 12) {
PORT_Memcpy(gcm->CTR, iv, AES_BLOCK_SIZE - 4);
gcm->CTR[12] = 0;
gcm->CTR[13] = 0;
gcm->CTR[14] = 0;
gcm->CTR[15] = 1;
} else {
/* If IV size is not 96 bits, then the initial counter value is GHASH
* of the IV */
ppc_aes_gcmHASH(gcm->Htbl, iv, ivLen, gcm->T);
ppc_aes_gcmTAG(
gcm->Htbl,
gcm->T,
ivLen,
0,
gcm->X0,
gcm->CTR);
/* TAG should be zero again */
PORT_Memset(gcm->T, 0, AES_BLOCK_SIZE);
}
/* Encrypt the initial counter, will be used to encrypt the GHASH value,
* in the end */
rv = (*gcm->cipher)(gcm->aes_context, gcm->X0, &j, AES_BLOCK_SIZE, gcm->CTR,
AES_BLOCK_SIZE, AES_BLOCK_SIZE);
if (rv != SECSuccess) {
return SECFailure;
}
/* Promote the counter by 1 */
gcm->CTR[14] += !(++gcm->CTR[15]);
gcm->CTR[13] += !(gcm->CTR[15]) && !(gcm->CTR[14]);
gcm->CTR[12] += !(gcm->CTR[15]) && !(gcm->CTR[14]) && !(gcm->CTR[13]);
/* Now hash AAD - it would actually make sense to seperate the context
* creation from the AAD, because that would allow to reuse the H, which
* only changes when the AES key changes, and not every package, like the
* IV and AAD */
ppc_aes_gcmHASH(gcm->Htbl, aad, aadLen, gcm->T);
gcm->Alen += aadLen;
return SECSuccess;
}
void
ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit)
{
PORT_Memset(gcm, 0, sizeof(ppc_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}
}
SECStatus
ppc_AES_GCM_EncryptUpdate(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
unsigned int j;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
if (UINT_MAX - inlen < tagBytes) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen + tagBytes) {
*outlen = inlen + tagBytes;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
ppc_aes_gcmCRYPT(
inbuf,
outbuf,
inlen,
gcm->CTR,
gcm->aes_context->k.expandedKey,
gcm->aes_context->Nr);
ppc_aes_gcmHASH(
gcm->Htbl,
outbuf,
inlen,
gcm->T);
gcm->Mlen += inlen;
ppc_aes_gcmTAG(
gcm->Htbl,
gcm->T,
gcm->Mlen,
gcm->Alen,
gcm->X0,
T);
*outlen = inlen + tagBytes;
for (j = 0; j < tagBytes; j++) {
outbuf[inlen + j] = T[j];
}
return SECSuccess;
}
SECStatus
ppc_AES_GCM_DecryptUpdate(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
const unsigned char *intag;
if (!gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
/* get the authentication block */
if (inlen < tagBytes) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
inlen -= tagBytes;
intag = inbuf + inlen;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
ppc_aes_gcmHASH(
gcm->Htbl,
inbuf,
inlen,
gcm->T);
ppc_aes_gcmCRYPT(
inbuf,
outbuf,
inlen,
gcm->CTR,
gcm->aes_context->k.expandedKey,
gcm->aes_context->Nr);
gcm->Mlen += inlen;
ppc_aes_gcmTAG(
gcm->Htbl,
gcm->T,
gcm->Mlen,
gcm->Alen,
gcm->X0,
T);
if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) {
memset(outbuf, 0, inlen);
*outlen = 0;
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
*outlen = inlen;
return SECSuccess;
}
SECStatus
ppc_AES_GCM_EncryptAEAD(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
SECStatus rv;
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_EncryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = gcm_GenerateIV(&gcm->gcm_iv, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulIvFixedBits, gcmParams->ivGenerator);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
ppc_aes_gcmCRYPT(inbuf, outbuf, inlen, gcm->CTR, gcm->aes_context->k.expandedKey,
gcm->aes_context->Nr);
ppc_aes_gcmHASH(gcm->Htbl, outbuf, inlen, gcm->T);
gcm->Mlen += inlen;
ppc_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
*outlen = inlen;
PORT_Memcpy(gcmParams->pTag, T, tagBytes);
return SECSuccess;
}
SECStatus
ppc_AES_GCM_DecryptAEAD(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize)
{
unsigned int tagBytes;
unsigned char T[AES_BLOCK_SIZE];
const unsigned char *intag;
const CK_GCM_MESSAGE_PARAMS *gcmParams =
(const CK_GCM_MESSAGE_PARAMS *)params;
SECStatus rv;
/* paramLen comes all the way from the application layer, make sure
* it's correct */
if (paramLen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* if we were initialized with the C_DecryptInit, we shouldn't be in this
* function */
if (gcm->ctr_context_init) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
// GCM has a 16 octet block, with a 32-bit block counter
// Limit in accordance with SP800-38D
if (sizeof(inlen) > 4 &&
inlen >= ((1ULL << 32) - 2) * AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxout < inlen) {
*outlen = inlen;
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
rv = ppc_aes_gcmInitCounter(gcm, gcmParams->pIv, gcmParams->ulIvLen,
gcmParams->ulTagBits, aad, aadLen);
if (rv != SECSuccess) {
return SECFailure;
}
tagBytes = (gcm->tagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
intag = gcmParams->pTag;
PORT_Assert(tagBytes != 0);
ppc_aes_gcmHASH(gcm->Htbl, inbuf, inlen, gcm->T);
ppc_aes_gcmCRYPT(inbuf, outbuf, inlen, gcm->CTR, gcm->aes_context->k.expandedKey,
gcm->aes_context->Nr);
gcm->Mlen += inlen;
ppc_aes_gcmTAG(gcm->Htbl, gcm->T, gcm->Mlen, gcm->Alen, gcm->X0, T);
if (NSS_SecureMemcmp(T, intag, tagBytes) != 0) {
memset(outbuf, 0, inlen);
*outlen = 0;
/* force a CKR_ENCRYPTED_DATA_INVALID error at in softoken */
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
*outlen = inlen;
return SECSuccess;
}

View file

@ -0,0 +1,76 @@
/******************************************************************************/
/* LICENSE: */
/* This submission to NSS is to be made available under the terms of the */
/* Mozilla Public License, v. 2.0. You can obtain one at http: */
/* //mozilla.org/MPL/2.0/. */
/******************************************************************************/
#ifndef PPC_GCM_H
#define PPC_GCM_H 1
#include "blapii.h"
typedef struct ppc_AES_GCMContextStr ppc_AES_GCMContext;
ppc_AES_GCMContext *ppc_AES_GCM_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *params);
void ppc_AES_GCM_DestroyContext(ppc_AES_GCMContext *gcm, PRBool freeit);
SECStatus ppc_AES_GCM_EncryptUpdate(ppc_AES_GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize);
SECStatus ppc_AES_GCM_DecryptUpdate(ppc_AES_GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize);
SECStatus ppc_AES_GCM_EncryptAEAD(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
SECStatus ppc_AES_GCM_DecryptAEAD(ppc_AES_GCMContext *gcm,
unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
const unsigned char *inbuf, unsigned int inlen,
void *params, unsigned int paramLen,
const unsigned char *aad, unsigned int aadLen,
unsigned int blocksize);
/* Prototypes of the functions defined in the assembler file. */
/* Prepares the constants used in the aggregated reduction method */
void ppc_aes_gcmINIT(unsigned char Htbl[8 * 16],
PRUint32 *KS,
int NR);
/* Produces the final GHASH value */
void ppc_aes_gcmTAG(unsigned char Htbl[8 * 16],
unsigned char *Tp,
unsigned long Mlen,
unsigned long Alen,
unsigned char *X0,
unsigned char *TAG);
/* Hashes the Additional Authenticated Data, should be used before enc/dec.
Operates on any length of data. Partial block is padded internally. */
void ppc_aes_gcmHASH(unsigned char Htbl[8 * 16],
const unsigned char *AAD,
unsigned long Alen,
unsigned char *Tp);
/* Crypt only, used in combination with ppc_aes_gcmAAD().
Operates on any length of data, however partial block should only be encrypted
at the last call, otherwise the result will be incorrect. */
void ppc_aes_gcmCRYPT(const unsigned char *PT,
unsigned char *CT,
unsigned long len,
unsigned char *CTRP,
PRUint32 *KS,
int NR);
#endif

File diff suppressed because it is too large Load diff

View file

@ -342,7 +342,7 @@ addToSeed(const SECItem *seed,
CHECK_MPI_OK(mp_init(&modulus));
SECITEM_TO_MPINT(*seed, &s); /* s = seed */
/* seed += addend */
if (addend < MP_DIGIT_MAX) {
if (sizeof(addend) < sizeof(mp_digit) || addend < MP_DIGIT_MAX) {
CHECK_MPI_OK(mp_add_d(&s, (mp_digit)addend, &s));
} else {
CHECK_MPI_OK(mp_init(&tmp));
@ -711,7 +711,7 @@ cleanup:
if (rv == SECFailure) {
mp_zero(prime);
if (prime_seed->data) {
SECITEM_FreeItem(prime_seed, PR_FALSE);
SECITEM_ZfreeItem(prime_seed, PR_FALSE);
}
*prime_gen_counter = 0;
}
@ -867,7 +867,7 @@ cleanup:
if (rv == SECFailure) {
mp_zero(prime);
if (prime_seed->data) {
SECITEM_FreeItem(prime_seed, PR_FALSE);
SECITEM_ZfreeItem(prime_seed, PR_FALSE);
}
*prime_gen_counter = 0;
}
@ -905,6 +905,7 @@ findQfromSeed(
*typePtr = FIPS186_1_TYPE;
return SECSuccess;
}
mp_zero(Q_);
return SECFailure;
}
/* 1024 could use FIPS186_1 or FIPS186_3 algorithms, we need to try
@ -954,21 +955,23 @@ findQfromSeed(
if ((offset < 0) ||
(PORT_Memcmp(&seed->data[offset], qseed.data, qseed.len) != 0)) {
/* we found q, but the seeds don't match. This isn't an
* accident, someone has been tweeking with the seeds, just
* fail a this point. */
* accident, someone has been tweeking with the seeds, just
* fail a this point. */
SECITEM_FreeItem(&qseed, PR_FALSE);
mp_zero(Q_);
return SECFailure;
}
*qseed_len = qseed.len;
*hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE;
*qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE);
SECITEM_ZfreeItem(&qseed, PR_FALSE);
return SECSuccess;
}
SECITEM_FreeItem(&qseed, PR_FALSE);
SECITEM_ZfreeItem(&qseed, PR_FALSE);
}
/* no hash algorithms found which match seed to Q, fail */
mp_zero(Q_);
return SECFailure;
}
@ -1069,6 +1072,7 @@ makePfromQandSeed(
CHECK_MPI_OK(mp_sub_d(&c, 1, &c)); /* c -= 1 */
CHECK_MPI_OK(mp_sub(&X, &c, P)); /* P = X - c */
cleanup:
PORT_Memset(V_j, 0, sizeof V_j);
mp_clear(&W);
mp_clear(&X);
mp_clear(&c);
@ -1077,8 +1081,12 @@ cleanup:
mp_clear(&tmp);
if (err) {
MP_TO_SEC_ERROR(err);
mp_zero(P);
return SECFailure;
}
if (rv != SECSuccess) {
mp_zero(P);
}
return rv;
}
@ -1128,6 +1136,9 @@ cleanup:
MP_TO_SEC_ERROR(err);
rv = SECFailure;
}
if (rv != SECSuccess) {
mp_zero(G);
}
return rv;
}
@ -1421,7 +1432,7 @@ step_5:
** "will give an acceptable probability of error."
*/
/*CHECK_SEC_OK( prm_RabinTest(&Q, &passed) );*/
err = mpp_pprime(&Q, prime_testcount_q(L, N));
err = mpp_pprime_secure(&Q, prime_testcount_q(L, N));
passed = (err == MP_YES) ? SECSuccess : SECFailure;
/* ******************************************************************
** Step 9. (Step 5 in 186-1) "If q is not prime, goto step 5 (1 in 186-1)."
@ -1474,7 +1485,7 @@ step_5:
** "Perform a robust primality test on p."
*/
/*CHECK_SEC_OK( prm_RabinTest(&P, &passed) );*/
err = mpp_pprime(&P, prime_testcount_p(L, N));
err = mpp_pprime_secure(&P, prime_testcount_p(L, N));
passed = (err == MP_YES) ? SECSuccess : SECFailure;
/* ******************************************************************
** Step 11.8. "If p is determined to be primed return VALID
@ -1534,10 +1545,10 @@ generate_G:
*pVfy = verify;
cleanup:
if (pseed.data) {
PORT_Free(pseed.data);
SECITEM_ZfreeItem(&pseed, PR_FALSE);
}
if (qseed.data) {
PORT_Free(qseed.data);
SECITEM_ZfreeItem(&qseed, PR_FALSE);
}
mp_clear(&P);
mp_clear(&Q);
@ -1558,7 +1569,7 @@ cleanup:
}
}
if (hit.data) {
SECITEM_FreeItem(&hit, PR_FALSE);
SECITEM_ZfreeItem(&hit, PR_FALSE);
}
return rv;
}
@ -1702,9 +1713,9 @@ PQG_VerifyParams(const PQGParams *params,
CHECK_MPI_OK(mp_mod(&P, &Q, &r));
CHECKPARAM(mp_cmp_d(&r, 1) == 0);
/* 5. Q is prime */
CHECKPARAM(mpp_pprime(&Q, prime_testcount_q(L, N)) == MP_YES);
CHECKPARAM(mpp_pprime_secure(&Q, prime_testcount_q(L, N)) == MP_YES);
/* 6. P is prime */
CHECKPARAM(mpp_pprime(&P, prime_testcount_p(L, N)) == MP_YES);
CHECKPARAM(mpp_pprime_secure(&P, prime_testcount_p(L, N)) == MP_YES);
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */
/* 7. counter < 4*L */
@ -1869,7 +1880,7 @@ cleanup:
mp_clear(&r);
mp_clear(&h);
if (pseed_.data) {
SECITEM_FreeItem(&pseed_, PR_FALSE);
SECITEM_ZfreeItem(&pseed_, PR_FALSE);
}
if (err) {
MP_TO_SEC_ERROR(err);
@ -1887,11 +1898,11 @@ PQG_DestroyParams(PQGParams *params)
if (params == NULL)
return;
if (params->arena != NULL) {
PORT_FreeArena(params->arena, PR_FALSE); /* don't zero it */
PORT_FreeArena(params->arena, PR_TRUE);
} else {
SECITEM_FreeItem(&params->prime, PR_FALSE); /* don't free prime */
SECITEM_FreeItem(&params->subPrime, PR_FALSE); /* don't free subPrime */
SECITEM_FreeItem(&params->base, PR_FALSE); /* don't free base */
SECITEM_ZfreeItem(&params->prime, PR_FALSE); /* don't free prime */
SECITEM_ZfreeItem(&params->subPrime, PR_FALSE); /* don't free subPrime */
SECITEM_ZfreeItem(&params->base, PR_FALSE); /* don't free base */
PORT_Free(params);
}
}
@ -1906,10 +1917,10 @@ PQG_DestroyVerify(PQGVerify *vfy)
if (vfy == NULL)
return;
if (vfy->arena != NULL) {
PORT_FreeArena(vfy->arena, PR_FALSE); /* don't zero it */
PORT_FreeArena(vfy->arena, PR_TRUE);
} else {
SECITEM_FreeItem(&vfy->seed, PR_FALSE); /* don't free seed */
SECITEM_FreeItem(&vfy->h, PR_FALSE); /* don't free h */
SECITEM_ZfreeItem(&vfy->seed, PR_FALSE); /* don't free seed */
SECITEM_ZfreeItem(&vfy->h, PR_FALSE); /* don't free h */
PORT_Free(vfy);
}
}

View file

@ -20,12 +20,15 @@
#include "gcm.h"
#include "mpi.h"
#if (!defined(IS_LITTLE_ENDIAN) && !defined(NSS_X86_OR_X64)) || \
(defined(__arm__) && !defined(__ARM_NEON) && !defined(__ARM_NEON__))
#if !defined(IS_LITTLE_ENDIAN) && !defined(NSS_X86_OR_X64)
// not test yet on big endian platform of arm
#undef USE_HW_AES
#endif
#ifdef __powerpc64__
#include "ppc-crypto.h"
#endif
#ifdef USE_HW_AES
#ifdef NSS_X86_OR_X64
#include "intel-aes.h"
@ -36,11 +39,8 @@
#ifdef INTEL_GCM
#include "intel-gcm.h"
#endif /* INTEL_GCM */
#ifdef _MSC_VER
#if _MSC_VER < 1900
#define inline
#endif
#if defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
#include "ppc-gcm.h"
#endif
/* Forward declarations */
@ -964,6 +964,7 @@ aes_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
} else {
rijndael_invkey_expansion(cx, key, Nk);
}
BLAPI_CLEAR_STACK(256)
}
cx->worker_cx = cx;
cx->destroy = NULL;
@ -1006,6 +1007,7 @@ AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
}
/* finally, set up any mode specific contexts */
cx->worker_aead = 0;
switch (mode) {
case NSS_AES_CTS:
cx->worker_cx = CTS_CreateContext(cx, cx->worker, iv);
@ -1020,21 +1022,36 @@ AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
cx->worker_cx = intel_AES_GCM_CreateContext(cx, cx->worker, iv);
cx->worker = (freeblCipherFunc)(encrypt ? intel_AES_GCM_EncryptUpdate
: intel_AES_GCM_DecryptUpdate);
cx->worker_aead = (freeblAeadFunc)(encrypt ? intel_AES_GCM_EncryptAEAD
: intel_AES_GCM_DecryptAEAD);
cx->destroy = (freeblDestroyFunc)intel_AES_GCM_DestroyContext;
cx->isBlock = PR_FALSE;
} else
#elif defined(USE_PPC_CRYPTO) && defined(PPC_GCM)
if (ppc_crypto_support() && (keysize % 8) == 0) {
cx->worker_cx = ppc_AES_GCM_CreateContext(cx, cx->worker, iv);
cx->worker = (freeblCipherFunc)(encrypt ? ppc_AES_GCM_EncryptUpdate
: ppc_AES_GCM_DecryptUpdate);
cx->worker_aead = (freeblAeadFunc)(encrypt ? ppc_AES_GCM_EncryptAEAD
: ppc_AES_GCM_DecryptAEAD);
cx->destroy = (freeblDestroyFunc)ppc_AES_GCM_DestroyContext;
cx->isBlock = PR_FALSE;
} else
#endif
{
cx->worker_cx = GCM_CreateContext(cx, cx->worker, iv);
cx->worker = (freeblCipherFunc)(encrypt ? GCM_EncryptUpdate
: GCM_DecryptUpdate);
cx->worker_aead = (freeblAeadFunc)(encrypt ? GCM_EncryptAEAD
: GCM_DecryptAEAD);
cx->destroy = (freeblDestroyFunc)GCM_DestroyContext;
cx->isBlock = PR_FALSE;
}
break;
case NSS_AES_CTR:
cx->worker_cx = CTR_CreateContext(cx, cx->worker, iv);
#if defined(USE_HW_AES) && defined(_MSC_VER)
#if defined(USE_HW_AES) && defined(_MSC_VER) && defined(NSS_X86_OR_X64)
if (aesni_support() && (keysize % 8) == 0) {
cx->worker = (freeblCipherFunc)CTR_Update_HW_AES;
} else
@ -1119,6 +1136,7 @@ AES_Encrypt(AESContext *cx, unsigned char *output,
const unsigned char *input, unsigned int inputLen)
{
/* Check args */
SECStatus rv;
if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@ -1153,8 +1171,10 @@ AES_Encrypt(AESContext *cx, unsigned char *output,
}
#endif
return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, AES_BLOCK_SIZE);
rv = (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, AES_BLOCK_SIZE);
BLAPI_CLEAR_STACK(256)
return rv;
}
/*
@ -1168,6 +1188,7 @@ AES_Decrypt(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
SECStatus rv;
/* Check args */
if (cx == NULL || output == NULL || (input == NULL && inputLen != 0)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -1177,11 +1198,68 @@ AES_Decrypt(AESContext *cx, unsigned char *output,
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if ((cx->mode != NSS_AES_GCM) && (maxOutputLen < inputLen)) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
*outputLen = inputLen;
rv = (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, AES_BLOCK_SIZE);
BLAPI_CLEAR_STACK(256)
return rv;
}
/*
* AES_Encrypt_AEAD
*
* Encrypt using GCM or CCM. include the nonce, extra data, and the tag
*/
SECStatus
AES_AEAD(AESContext *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen,
void *params, unsigned int paramsLen,
const unsigned char *aad, unsigned int aadLen)
{
SECStatus rv;
/* Check args */
if (cx == NULL || output == NULL || (input == NULL && inputLen != 0) || (aad == NULL && aadLen != 0) || params == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cx->worker_aead == NULL) {
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
return SECFailure;
}
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
*outputLen = inputLen;
return (*cx->worker)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, AES_BLOCK_SIZE);
#if UINT_MAX > MP_32BIT_MAX
/*
* we can guarentee that GSM won't overlfow if we limit the input to
* 2^36 bytes. For simplicity, we are limiting it to 2^32 for now.
*
* We do it here to cover both hardware and software GCM operations.
*/
{
PR_STATIC_ASSERT(sizeof(unsigned int) > 4);
}
if (inputLen > MP_32BIT_MAX) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
#else
/* if we can't pass in a 32_bit number, then no such check needed */
{
PR_STATIC_ASSERT(sizeof(unsigned int) <= 4);
}
#endif
rv = (*cx->worker_aead)(cx->worker_cx, output, outputLen, maxOutputLen,
input, inputLen, params, paramsLen, aad, aadLen,
AES_BLOCK_SIZE);
BLAPI_CLEAR_STACK(256)
return rv;
}

View file

@ -69,6 +69,7 @@ struct AESContextStr {
unsigned int Nr;
freeblCipherFunc worker;
unsigned char iv[AES_BLOCK_SIZE];
freeblAeadFunc worker_aead;
freeblDestroyFunc destroy;
void *worker_cx;
PRBool isBlock;

View file

@ -17,45 +17,43 @@
#define WORD_BE(b0, b1, b2, b3) \
(((b0) << 24) | ((b1) << 16) | ((b2) << 8) | b3)
static const PRUint8 __S[256] =
{
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22,
};
static const PRUint8 __S[256] = {
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
};
static const PRUint8 __SInv[256] =
{
82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125
};
static const PRUint8 __SInv[256] = {
82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125
};
/* GF_MULTIPLY
*

View file

@ -22,6 +22,12 @@
#include "secitem.h"
#include "blapii.h"
/* The minimal required randomness is 64 bits */
/* EXP_BLINDING_RANDOMNESS_LEN is the length of the randomness in mp_digits */
/* for 32 bits platforts it is 2 mp_digits (= 2 * 32 bits), for 64 bits it is equal to 128 bits */
#define EXP_BLINDING_RANDOMNESS_LEN ((128 + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT)
#define EXP_BLINDING_RANDOMNESS_LEN_BYTES (EXP_BLINDING_RANDOMNESS_LEN * sizeof(mp_digit))
/*
** Number of times to attempt to generate a prime (p or q) from a random
** seed (the seed changes for each iteration).
@ -64,6 +70,8 @@ struct RSABlindingParamsStr {
SECItem modulus; /* list element "key" */
blindingParams *free, *bp; /* Blinding parameters queue */
blindingParams array[RSA_BLINDING_PARAMS_MAX_CACHE_SIZE];
/* precalculate montegomery reduction value */
mp_digit n0i; /* n0i = -( n & MP_DIGIT) ** -1 mod mp_RADIX */
};
typedef struct RSABlindingParamsStr RSABlindingParams;
@ -208,7 +216,7 @@ generate_prime(mp_int *prime, int primeLen)
pb[0] |= 0xC0; /* set two high-order bits */
pb[primeLen - 1] |= 0x01; /* set low-order bit */
CHECK_MPI_OK(mp_read_unsigned_octets(prime, pb, primeLen));
err = mpp_make_prime(prime, primeLen * 8, PR_FALSE);
err = mpp_make_prime_secure(prime, primeLen * 8, PR_FALSE);
if (err != MP_NO)
goto cleanup;
/* keep going while err == MP_NO */
@ -391,7 +399,7 @@ rsa_is_prime(mp_int *p)
}
/* If that passed, run some Miller-Rabin tests */
res = mpp_pprime(p, 2);
res = mpp_pprime_secure(p, 2);
return res;
}
@ -893,6 +901,9 @@ cleanup:
static unsigned int
rsa_modulusLen(SECItem *modulus)
{
if (modulus->len == 0) {
return 0;
};
unsigned char byteZero = modulus->data[0];
unsigned int modLen = modulus->len - !byteZero;
return modLen;
@ -925,6 +936,13 @@ RSA_PublicKeyOp(RSAPublicKey *key,
CHECK_MPI_OK(mp_init(&c));
modLen = rsa_modulusLen(&key->modulus);
expLen = rsa_modulusLen(&key->publicExponent);
if (modLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
goto cleanup;
}
/* 1. Obtain public key (n, e) */
if (BAD_RSA_KEY_SIZE(modLen, expLen)) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
@ -1003,6 +1021,13 @@ static SECStatus
rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c)
{
mp_int p, q, d_p, d_q, qInv;
/*
The length of the randomness comes from the papers:
https://link.springer.com/chapter/10.1007/978-3-642-29912-4_7
https://link.springer.com/chapter/10.1007/978-3-642-21554-4_5.
*/
mp_int blinding_dp, blinding_dq, r1, r2;
unsigned char random_block[EXP_BLINDING_RANDOMNESS_LEN_BYTES];
mp_int m1, m2, h, ctmp;
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
@ -1015,6 +1040,11 @@ rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c)
MP_DIGITS(&m2) = 0;
MP_DIGITS(&h) = 0;
MP_DIGITS(&ctmp) = 0;
MP_DIGITS(&blinding_dp) = 0;
MP_DIGITS(&blinding_dq) = 0;
MP_DIGITS(&r1) = 0;
MP_DIGITS(&r2) = 0;
CHECK_MPI_OK(mp_init(&p));
CHECK_MPI_OK(mp_init(&q));
CHECK_MPI_OK(mp_init(&d_p));
@ -1024,12 +1054,44 @@ rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c)
CHECK_MPI_OK(mp_init(&m2));
CHECK_MPI_OK(mp_init(&h));
CHECK_MPI_OK(mp_init(&ctmp));
CHECK_MPI_OK(mp_init(&blinding_dp));
CHECK_MPI_OK(mp_init(&blinding_dq));
CHECK_MPI_OK(mp_init_size(&r1, EXP_BLINDING_RANDOMNESS_LEN));
CHECK_MPI_OK(mp_init_size(&r2, EXP_BLINDING_RANDOMNESS_LEN));
/* copy private key parameters into mp integers */
SECITEM_TO_MPINT(key->prime1, &p); /* p */
SECITEM_TO_MPINT(key->prime2, &q); /* q */
SECITEM_TO_MPINT(key->exponent1, &d_p); /* d_p = d mod (p-1) */
SECITEM_TO_MPINT(key->exponent2, &d_q); /* d_q = d mod (q-1) */
SECITEM_TO_MPINT(key->coefficient, &qInv); /* qInv = q**-1 mod p */
// blinding_dp = 1
CHECK_MPI_OK(mp_set_int(&blinding_dp, 1));
// blinding_dp = p - 1
CHECK_MPI_OK(mp_sub(&p, &blinding_dp, &blinding_dp));
// generating a random value
RNG_GenerateGlobalRandomBytes(random_block, EXP_BLINDING_RANDOMNESS_LEN_BYTES);
MP_USED(&r1) = EXP_BLINDING_RANDOMNESS_LEN;
memcpy(MP_DIGITS(&r1), random_block, sizeof(random_block));
// blinding_dp = random * (p - 1)
CHECK_MPI_OK(mp_mul(&blinding_dp, &r1, &blinding_dp));
//d_p = d_p + random * (p - 1)
CHECK_MPI_OK(mp_add(&d_p, &blinding_dp, &d_p));
// blinding_dq = 1
CHECK_MPI_OK(mp_set_int(&blinding_dq, 1));
// blinding_dq = q - 1
CHECK_MPI_OK(mp_sub(&q, &blinding_dq, &blinding_dq));
// generating a random value
RNG_GenerateGlobalRandomBytes(random_block, EXP_BLINDING_RANDOMNESS_LEN_BYTES);
memcpy(MP_DIGITS(&r2), random_block, sizeof(random_block));
MP_USED(&r2) = EXP_BLINDING_RANDOMNESS_LEN;
// blinding_dq = random * (q - 1)
CHECK_MPI_OK(mp_mul(&blinding_dq, &r2, &blinding_dq));
//d_q = d_q + random * (q-1)
CHECK_MPI_OK(mp_add(&d_q, &blinding_dq, &d_q));
/* 1. m1 = c**d_p mod p */
CHECK_MPI_OK(mp_mod(c, &p, &ctmp));
CHECK_MPI_OK(mp_exptmod(&ctmp, &d_p, &p, &m1));
@ -1052,6 +1114,10 @@ cleanup:
mp_clear(&m2);
mp_clear(&h);
mp_clear(&ctmp);
mp_clear(&blinding_dp);
mp_clear(&blinding_dq);
mp_clear(&r1);
mp_clear(&r2);
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
@ -1146,6 +1212,8 @@ generate_blinding_params(RSAPrivateKey *key, mp_int *f, mp_int *g, mp_int *n,
CHECK_MPI_OK(mp_exptmod(&k, &e, n, f));
/* g = k**-1 mod n */
CHECK_MPI_OK(mp_invmod(&k, n, g));
/* g in montgomery form.. */
CHECK_MPI_OK(mp_to_mont(g, n, g));
cleanup:
if (kb)
PORT_ZFree(kb, modLen);
@ -1182,13 +1250,16 @@ init_blinding_params(RSABlindingParams *rsabp, RSAPrivateKey *key,
rsabp->bp = NULL;
rsabp->free = bp;
/* precalculate montgomery reduction parameter */
rsabp->n0i = mp_calculate_mont_n0i(n);
/* List elements are keyed using the modulus */
return SECITEM_CopyItem(NULL, &rsabp->modulus, &key->modulus);
}
static SECStatus
get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
mp_int *f, mp_int *g)
mp_int *f, mp_int *g, mp_digit *n0i)
{
RSABlindingParams *rsabp = NULL;
blindingParams *bpUnlinked = NULL;
@ -1248,11 +1319,18 @@ get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
/* We've found (or created) the RSAblindingParams struct for this key.
* Now, search its list of ready blinding params for a usable one.
*/
*n0i = rsabp->n0i;
while (0 != (bp = rsabp->bp)) {
#ifndef UNSAFE_FUZZER_MODE
if (--(bp->counter) > 0)
#endif
{
#ifdef UNSAFE_FUZZER_MODE
/* Found a match and there are still remaining uses left */
/* Return the parameters */
CHECK_MPI_OK(mp_copy(&bp->f, f));
CHECK_MPI_OK(mp_copy(&bp->g, g));
PZ_Unlock(blindingParamsList.lock);
return SECSuccess;
#else
if (--(bp->counter) > 0) {
/* Found a match and there are still remaining uses left */
/* Return the parameters */
CHECK_MPI_OK(mp_copy(&bp->f, f));
@ -1282,6 +1360,7 @@ get_blinding_params(RSAPrivateKey *key, mp_int *n, unsigned int modLen,
}
PZ_Unlock(blindingParamsList.lock);
return SECSuccess;
#endif
}
/* We did not find a usable set of blinding params. Can we make one? */
/* Find a free bp struct. */
@ -1355,6 +1434,7 @@ cleanup:
if (err) {
MP_TO_SEC_ERROR(err);
}
*n0i = 0;
return SECFailure;
}
@ -1374,12 +1454,17 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
mp_err err;
mp_int n, c, m;
mp_int f, g;
mp_digit n0i;
if (!key || !output || !input) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* check input out of range (needs to be in range [0..n-1]) */
modLen = rsa_modulusLen(&key->modulus);
if (modLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
offset = (key->modulus.data[0] == 0) ? 1 : 0; /* may be leading 0 */
if (memcmp(input, key->modulus.data + offset, modLen) >= 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -1401,7 +1486,7 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
** blinding factor
*/
if (nssRSAUseBlinding) {
CHECK_SEC_OK(get_blinding_params(key, &n, modLen, &f, &g));
CHECK_SEC_OK(get_blinding_params(key, &n, modLen, &f, &g, &n0i));
/* c' = c*f mod n */
CHECK_MPI_OK(mp_mulmod(&c, &f, &n, &c));
}
@ -1422,7 +1507,7 @@ rsa_PrivateKeyOp(RSAPrivateKey *key,
*/
if (nssRSAUseBlinding) {
/* m = m'*g mod n */
CHECK_MPI_OK(mp_mulmod(&m, &g, &n, &m));
CHECK_MPI_OK(mp_mulmontmodCT(&m, &g, &n, n0i, &m));
}
err = mp_to_fixlen_octets(&m, output, modLen);
if (err >= 0)
@ -1593,7 +1678,7 @@ RSA_Cleanup(void)
mp_clear(&bp->f);
mp_clear(&bp->g);
}
SECITEM_FreeItem(&rsabp->modulus, PR_FALSE);
SECITEM_ZfreeItem(&rsabp->modulus, PR_FALSE);
PORT_Free(rsabp);
}

View file

@ -80,6 +80,10 @@ constantTimeCondition(unsigned int c,
static unsigned int
rsa_modulusLen(SECItem *modulus)
{
if (modulus->len == 0) {
return 0;
}
unsigned char byteZero = modulus->data[0];
unsigned int modLen = modulus->len - !byteZero;
return modLen;
@ -88,9 +92,17 @@ rsa_modulusLen(SECItem *modulus)
static unsigned int
rsa_modulusBits(SECItem *modulus)
{
if (modulus->len == 0) {
return 0;
}
unsigned char byteZero = modulus->data[0];
unsigned int numBits = (modulus->len - 1) * 8;
if (byteZero == 0 && modulus->len == 1) {
return 0;
}
if (byteZero == 0) {
numBits -= 8;
byteZero = modulus->data[1];
@ -116,7 +128,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
unsigned char *block;
unsigned char *bp;
unsigned int padLen;
int i, j;
unsigned int i, j;
SECStatus rv;
block = (unsigned char *)PORT_Alloc(modulusLen);
@ -147,7 +159,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
padLen = modulusLen - data->len - 3;
PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
PORT_Free(block);
PORT_ZFree(block, modulusLen);
return NULL;
}
PORT_Memset(bp, RSA_BLOCK_PRIVATE_PAD_OCTET, padLen);
@ -176,7 +188,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
padLen = modulusLen - (data->len + 3);
PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
PORT_Free(block);
PORT_ZFree(block, modulusLen);
return NULL;
}
j = modulusLen - 2;
@ -205,7 +217,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
}
}
if (rv != SECSuccess) {
PORT_Free(block);
PORT_ZFree(block, modulusLen);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return NULL;
}
@ -216,7 +228,7 @@ rsa_FormatOneBlock(unsigned modulusLen,
default:
PORT_Assert(0);
PORT_Free(block);
PORT_ZFree(block, modulusLen);
return NULL;
}
@ -932,7 +944,162 @@ failure:
return SECFailure;
}
/* XXX Doesn't set error code */
static HMACContext *
rsa_GetHMACContext(const SECHashObject *hash, RSAPrivateKey *key,
const unsigned char *input, unsigned int inputLen)
{
unsigned char keyHash[HASH_LENGTH_MAX];
void *hashContext;
HMACContext *hmac = NULL;
unsigned int privKeyLen = key->privateExponent.len;
unsigned int keyLen;
SECStatus rv;
/* first get the key hash (should store in the key structure) */
PORT_Memset(keyHash, 0, sizeof(keyHash));
hashContext = (*hash->create)();
if (hashContext == NULL) {
return NULL;
}
(*hash->begin)(hashContext);
if (privKeyLen < inputLen) {
int padLen = inputLen - privKeyLen;
while (padLen > sizeof(keyHash)) {
(*hash->update)(hashContext, keyHash, sizeof(keyHash));
padLen -= sizeof(keyHash);
}
(*hash->update)(hashContext, keyHash, padLen);
}
(*hash->update)(hashContext, key->privateExponent.data, privKeyLen);
(*hash->end)(hashContext, keyHash, &keyLen, sizeof(keyHash));
(*hash->destroy)(hashContext, PR_TRUE);
/* now create the hmac key */
hmac = HMAC_Create(hash, keyHash, keyLen, PR_TRUE);
if (hmac == NULL) {
PORT_Memset(keyHash, 0, sizeof(keyHash));
return NULL;
}
HMAC_Begin(hmac);
HMAC_Update(hmac, input, inputLen);
rv = HMAC_Finish(hmac, keyHash, &keyLen, sizeof(keyHash));
if (rv != SECSuccess) {
PORT_Memset(keyHash, 0, sizeof(keyHash));
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
}
/* Finally set the new key into the hash context. We
* reuse the original context allocated above so we don't
* need to allocate and free another one */
rv = HMAC_ReInit(hmac, hash, keyHash, keyLen, PR_TRUE);
PORT_Memset(keyHash, 0, sizeof(keyHash));
if (rv != SECSuccess) {
HMAC_Destroy(hmac, PR_TRUE);
return NULL;
}
return hmac;
}
static SECStatus
rsa_HMACPrf(HMACContext *hmac, const char *label, int labelLen,
int hashLength, unsigned char *output, int length)
{
unsigned char iterator[2] = { 0, 0 };
unsigned char encodedLen[2] = { 0, 0 };
unsigned char hmacLast[HASH_LENGTH_MAX];
unsigned int left = length;
unsigned int hashReturn;
SECStatus rv = SECSuccess;
/* encodedLen is in bits, length is in bytes, thus the shifts
* do an implied multiply by 8 */
encodedLen[0] = (length >> 5) & 0xff;
encodedLen[1] = (length << 3) & 0xff;
while (left > hashLength) {
HMAC_Begin(hmac);
HMAC_Update(hmac, iterator, 2);
HMAC_Update(hmac, (const unsigned char *)label, labelLen);
HMAC_Update(hmac, encodedLen, 2);
rv = HMAC_Finish(hmac, output, &hashReturn, hashLength);
if (rv != SECSuccess) {
return rv;
}
iterator[1]++;
if (iterator[1] == 0)
iterator[0]++;
left -= hashLength;
output += hashLength;
}
if (left) {
HMAC_Begin(hmac);
HMAC_Update(hmac, iterator, 2);
HMAC_Update(hmac, (const unsigned char *)label, labelLen);
HMAC_Update(hmac, encodedLen, 2);
rv = HMAC_Finish(hmac, hmacLast, &hashReturn, sizeof(hmacLast));
if (rv != SECSuccess) {
return rv;
}
PORT_Memcpy(output, hmacLast, left);
PORT_Memset(hmacLast, 0, sizeof(hmacLast));
}
return rv;
}
/* This function takes a 16-bit input number and
* creates the smallest mask which covers
* the whole number. Examples:
* 0x81 -> 0xff
* 0x1af -> 0x1ff
* 0x4d1 -> 0x7ff
*/
static int
makeMask16(int len)
{
// or the high bit in each bit location
len |= (len >> 1);
len |= (len >> 2);
len |= (len >> 4);
len |= (len >> 8);
return len;
}
#define STRING_AND_LENGTH(s) s, sizeof(s) - 1
static int
rsa_GetErrorLength(HMACContext *hmac, int hashLen, int maxLegalLen)
{
unsigned char out[128 * 2];
unsigned char *outp;
int outLength = 0;
int lengthMask;
SECStatus rv;
lengthMask = makeMask16(maxLegalLen);
rv = rsa_HMACPrf(hmac, STRING_AND_LENGTH("length"), hashLen,
out, sizeof(out));
if (rv != SECSuccess) {
return -1;
}
for (outp = out; outp < out + sizeof(out); outp += 2) {
int candidate = outp[0] << 8 | outp[1];
candidate = candidate & lengthMask;
outLength = PORT_CT_SEL(PORT_CT_LT(candidate, maxLegalLen),
candidate, outLength);
}
PORT_Memset(out, 0, sizeof(out));
return outLength;
}
/*
* This function can only fail in environmental cases: Programming errors
* and out of memory situations. It can't fail if the keys are valid and
* the inputs are the proper size. If the actual RSA decryption fails, a
* fake value and a fake length, both of which have already been generated
* based on the key and input, are returned.
* Applications are expected to detect decryption failures based on the fact
* that the decrypted value (usually a key) doesn't validate. The prevents
* Blecheinbaucher style attacks against the key. */
SECStatus
RSA_DecryptBlock(RSAPrivateKey *key,
unsigned char *output,
@ -941,56 +1108,122 @@ RSA_DecryptBlock(RSAPrivateKey *key,
const unsigned char *input,
unsigned int inputLen)
{
PRInt8 rv;
SECStatus rv;
PRUint32 fail;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
unsigned char *buffer = NULL;
unsigned int outLen = 0;
unsigned int copyOutLen = modulusLen - 11;
unsigned char *errorBuffer = NULL;
unsigned char *bp = NULL;
unsigned char *ep = NULL;
unsigned int outLen = modulusLen;
unsigned int maxLegalLen = modulusLen - 10;
unsigned int errorLength;
const SECHashObject *hashObj;
HMACContext *hmac = NULL;
/* failures in the top section indicate failures in the environment
* (memory) or the library. OK to return errors in these cases because
* it doesn't provide any oracle information to attackers. */
if (inputLen != modulusLen || modulusLen < 10) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (copyOutLen > maxOutputLen) {
copyOutLen = maxOutputLen;
}
// Allocate enough space to decrypt + copyOutLen to allow copying outLen later.
buffer = PORT_ZAlloc(modulusLen + 1 + copyOutLen);
/* Allocate enough space to decrypt */
buffer = PORT_ZAlloc(modulusLen);
if (!buffer) {
return SECFailure;
goto loser;
}
errorBuffer = PORT_ZAlloc(modulusLen);
if (!errorBuffer) {
goto loser;
}
hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
if (hashObj == NULL) {
goto loser;
}
// rv is 0 if everything is going well and 1 if an error occurs.
rv = RSA_PrivateKeyOp(key, buffer, input) != SECSuccess;
rv |= (buffer[0] != RSA_BLOCK_FIRST_OCTET) |
(buffer[1] != (unsigned char)RSA_BlockPublic);
/* calculate the values to return in the error case rather than
* the actual returned values. This data is the same for the
* same input and private key. */
hmac = rsa_GetHMACContext(hashObj, key, input, inputLen);
if (hmac == NULL) {
goto loser;
}
errorLength = rsa_GetErrorLength(hmac, hashObj->length, maxLegalLen);
if (((int)errorLength) < 0) {
goto loser;
}
/* we always have to generate a full moduluslen error string. Otherwise
* we create a timing dependency on errorLength, which could be used to
* determine the difference between errorLength and outputLen and tell
* us that there was a pkcs1 decryption failure */
rv = rsa_HMACPrf(hmac, STRING_AND_LENGTH("message"),
hashObj->length, errorBuffer, modulusLen);
if (rv != SECSuccess) {
goto loser;
}
// There have to be at least 8 bytes of padding.
HMAC_Destroy(hmac, PR_TRUE);
hmac = NULL;
/* From here on out, we will always return success. If there is
* an error, we will return deterministic output based on the key
* and the input data. */
rv = RSA_PrivateKeyOp(key, buffer, input);
fail = PORT_CT_NE(rv, SECSuccess);
fail |= PORT_CT_NE(buffer[0], RSA_BLOCK_FIRST_OCTET) | PORT_CT_NE(buffer[1], RSA_BlockPublic);
/* There have to be at least 8 bytes of padding. */
for (i = 2; i < 10; i++) {
rv |= buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET;
fail |= PORT_CT_EQ(buffer[i], RSA_BLOCK_AFTER_PAD_OCTET);
}
for (i = 10; i < modulusLen; i++) {
unsigned int newLen = modulusLen - i - 1;
unsigned int c = (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) & (outLen == 0);
outLen = constantTimeCondition(c, newLen, outLen);
PRUint32 condition = PORT_CT_EQ(buffer[i], RSA_BLOCK_AFTER_PAD_OCTET) & PORT_CT_EQ(outLen, modulusLen);
outLen = PORT_CT_SEL(condition, newLen, outLen);
}
rv |= outLen == 0;
rv |= outLen > maxOutputLen;
// this can only happen if a zero wasn't found above
fail |= PORT_CT_GE(outLen, modulusLen);
// Note that output is set even if SECFailure is returned.
PORT_Memcpy(output, buffer + modulusLen - outLen, copyOutLen);
*outputLen = constantTimeCondition(outLen > maxOutputLen, maxOutputLen,
outLen);
outLen = PORT_CT_SEL(fail, errorLength, outLen);
/* index into the correct buffer. Do it before we truncate outLen if the
* application was asking for less data than we can return */
bp = buffer + modulusLen - outLen;
ep = errorBuffer + modulusLen - outLen;
/* at this point, outLen returns no information about decryption failures,
* no need to hide its value. maxOutputLen is how much data the
* application is expecting, which is also not sensitive. */
if (outLen > maxOutputLen) {
outLen = maxOutputLen;
}
/* we can't use PORT_Memcpy because caching could create a time dependency
* on the status of fail. */
for (i = 0; i < outLen; i++) {
output[i] = PORT_CT_SEL(fail, ep[i], bp[i]);
}
*outputLen = outLen;
PORT_Free(buffer);
PORT_Free(errorBuffer);
for (i = 1; i < sizeof(rv) * 8; i <<= 1) {
rv |= rv << i;
return SECSuccess;
loser:
if (hmac) {
HMAC_Destroy(hmac, PR_TRUE);
}
return (SECStatus)rv;
PORT_Free(buffer);
PORT_Free(errorBuffer);
return SECFailure;
}
/*
@ -1409,6 +1642,7 @@ RSA_CheckSignRecover(RSAPublicKey *key,
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
unsigned char *buffer = NULL;
unsigned int padLen;
if (sigLen != modulusLen) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
@ -1446,6 +1680,11 @@ RSA_CheckSignRecover(RSAPublicKey *key,
goto done;
}
}
padLen = i - 2;
if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
goto done;
}
if (*outputLen == 0) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
goto done;

View file

@ -0,0 +1,36 @@
Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain copyright notices,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of the CRYPTOGAMS nor the names of its
copyright holder and contributors may be used to endorse or
promote products derived from this software without specific
prior written permission.
ALTERNATIVELY, provided that this notice is retained in full, this
product may be distributed under the terms of the GNU General Public
License (GPL), in which case the provisions of the GPL apply INSTEAD OF
those given above.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,19 @@
#!/bin/sh
#
# Run the scripts in this folder, generating the assembly,
#
perl sha512p8-ppc.pl linux64le sha512-p8.s
# Add the license mention
cat > hdr << "EOF"
# Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
# All rights reserved.
# See the full LICENSE under scripts/.
EOF
cat hdr sha512-p8.s > ../sha512-p8.s
# Cleanup
rm hdr sha512-p8.s

View file

@ -0,0 +1,352 @@
#!/usr/bin/env perl
# PowerPC assembler distiller by \@dot-asm.
################################################################
# Recognized "flavour"-s are:
#
# linux{32|64}[le] GNU assembler and ELF symbol decorations,
# with little-endian option
# linux64v2 GNU asssembler and big-endian instantiation
# of latest ELF specification
# aix{32|64} AIX assembler and symbol decorations
# osx{32|64} Mac OS X assembler and symbol decoratons
my $flavour = shift;
my $output = shift;
open STDOUT,">$output" || die "can't open $output: $!";
my %GLOBALS;
my %TYPES;
my $dotinlocallabels=($flavour=~/linux/)?1:0;
################################################################
# directives which need special treatment on different platforms
################################################################
my $type = sub {
my ($dir,$name,$type) = @_;
$TYPES{$name} = $type;
if ($flavour =~ /linux/) {
$name =~ s|^\.||;
".type $name,$type";
} else {
"";
}
};
my $globl = sub {
my $junk = shift;
my $name = shift;
my $global = \$GLOBALS{$name};
my $type = \$TYPES{$name};
my $ret;
$name =~ s|^\.||;
SWITCH: for ($flavour) {
/aix/ && do { if (!$$type) {
$$type = "\@function";
}
if ($$type =~ /function/) {
$name = ".$name";
}
last;
};
/osx/ && do { $name = "_$name";
last;
};
/linux.*(32|64(le|v2))/
&& do { $ret .= ".globl $name";
if (!$$type) {
$ret .= "\n.type $name,\@function";
$$type = "\@function";
}
last;
};
/linux.*64/ && do { $ret .= ".globl $name";
if (!$$type) {
$ret .= "\n.type $name,\@function";
$$type = "\@function";
}
if ($$type =~ /function/) {
$ret .= "\n.section \".opd\",\"aw\"";
$ret .= "\n.align 3";
$ret .= "\n$name:";
$ret .= "\n.quad .$name,.TOC.\@tocbase,0";
$ret .= "\n.previous";
$name = ".$name";
}
last;
};
}
$ret = ".globl $name" if (!$ret);
$$global = $name;
$ret;
};
my $text = sub {
my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
$ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64(le|v2)/);
$ret;
};
my $machine = sub {
my $junk = shift;
my $arch = shift;
if ($flavour =~ /osx/)
{ $arch =~ s/\"//g;
$arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any");
}
".machine $arch";
};
my $size = sub {
if ($flavour =~ /linux/)
{ shift;
my $name = shift;
my $real = $GLOBALS{$name} ? \$GLOBALS{$name} : \$name;
my $ret = ".size $$real,.-$$real";
$name =~ s|^\.||;
if ($$real ne $name) {
$ret .= "\n.size $name,.-$$real";
}
$ret;
}
else
{ ""; }
};
my $asciz = sub {
shift;
my $line = join(",",@_);
if ($line =~ /^"(.*)"$/)
{ ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; }
else
{ ""; }
};
my $quad = sub {
shift;
my @ret;
my ($hi,$lo);
for (@_) {
if (/^0x([0-9a-f]*?)([0-9a-f]{1,8})$/io)
{ $hi=$1?"0x$1":"0"; $lo="0x$2"; }
elsif (/^([0-9]+)$/o)
{ $hi=$1>>32; $lo=$1&0xffffffff; } # error-prone with 32-bit perl
else
{ $hi=undef; $lo=$_; }
if (defined($hi))
{ push(@ret,$flavour=~/le$/o?".long\t$lo,$hi":".long\t$hi,$lo"); }
else
{ push(@ret,".quad $lo"); }
}
join("\n",@ret);
};
################################################################
# simplified mnemonics not handled by at least one assembler
################################################################
my $cmplw = sub {
my $f = shift;
my $cr = 0; $cr = shift if ($#_>1);
# Some out-of-date 32-bit GNU assembler just can't handle cmplw...
($flavour =~ /linux.*32/) ?
" .long ".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 :
" cmplw ".join(',',$cr,@_);
};
my $bdnz = sub {
my $f = shift;
my $bo = $f=~/[\+\-]/ ? 16+9 : 16; # optional "to be taken" hint
" bc $bo,0,".shift;
} if ($flavour!~/linux/);
my $bltlr = sub {
my $f = shift;
my $bo = $f=~/\-/ ? 12+2 : 12; # optional "not to be taken" hint
($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
" .long ".sprintf "0x%x",19<<26|$bo<<21|16<<1 :
" bclr $bo,0";
};
my $bnelr = sub {
my $f = shift;
my $bo = $f=~/\-/ ? 4+2 : 4; # optional "not to be taken" hint
($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
" .long ".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 :
" bclr $bo,2";
};
my $beqlr = sub {
my $f = shift;
my $bo = $f=~/-/ ? 12+2 : 12; # optional "not to be taken" hint
($flavour =~ /linux/) ? # GNU as doesn't allow most recent hints
" .long ".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 :
" bclr $bo,2";
};
# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two
# arguments is 64, with "operand out of range" error.
my $extrdi = sub {
my ($f,$ra,$rs,$n,$b) = @_;
$b = ($b+$n)&63; $n = 64-$n;
" rldicl $ra,$rs,$b,$n";
};
my $vmr = sub {
my ($f,$vx,$vy) = @_;
" vor $vx,$vy,$vy";
};
# Some ABIs specify vrsave, special-purpose register #256, as reserved
# for system use.
my $no_vrsave = ($flavour =~ /aix|linux64(le|v2)/);
my $mtspr = sub {
my ($f,$idx,$ra) = @_;
if ($idx == 256 && $no_vrsave) {
" or $ra,$ra,$ra";
} else {
" mtspr $idx,$ra";
}
};
my $mfspr = sub {
my ($f,$rd,$idx) = @_;
if ($idx == 256 && $no_vrsave) {
" li $rd,-1";
} else {
" mfspr $rd,$idx";
}
};
# PowerISA 2.06 stuff
sub vsxmem_op {
my ($f, $vrt, $ra, $rb, $op) = @_;
" .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|($rb<<11)|($op*2+1);
}
# made-up unaligned memory reference AltiVec/VMX instructions
my $lvx_u = sub { vsxmem_op(@_, 844); }; # lxvd2x
my $stvx_u = sub { vsxmem_op(@_, 972); }; # stxvd2x
my $lvdx_u = sub { vsxmem_op(@_, 588); }; # lxsdx
my $stvdx_u = sub { vsxmem_op(@_, 716); }; # stxsdx
my $lvx_4w = sub { vsxmem_op(@_, 780); }; # lxvw4x
my $stvx_4w = sub { vsxmem_op(@_, 908); }; # stxvw4x
my $lvx_splt = sub { vsxmem_op(@_, 332); }; # lxvdsx
# VSX instruction[s] masqueraded as made-up AltiVec/VMX
my $vpermdi = sub { # xxpermdi
my ($f, $vrt, $vra, $vrb, $dm) = @_;
$dm = oct($dm) if ($dm =~ /^0/);
" .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($dm<<8)|(10<<3)|7;
};
# PowerISA 2.07 stuff
sub vcrypto_op {
my ($f, $vrt, $vra, $vrb, $op) = @_;
" .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op;
}
sub vfour {
my ($f, $vrt, $vra, $vrb, $vrc, $op) = @_;
" .long ".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($vrc<<6)|$op;
};
my $vcipher = sub { vcrypto_op(@_, 1288); };
my $vcipherlast = sub { vcrypto_op(@_, 1289); };
my $vncipher = sub { vcrypto_op(@_, 1352); };
my $vncipherlast= sub { vcrypto_op(@_, 1353); };
my $vsbox = sub { vcrypto_op(@_, 0, 1480); };
my $vshasigmad = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1730); };
my $vshasigmaw = sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1666); };
my $vpmsumb = sub { vcrypto_op(@_, 1032); };
my $vpmsumd = sub { vcrypto_op(@_, 1224); };
my $vpmsubh = sub { vcrypto_op(@_, 1096); };
my $vpmsumw = sub { vcrypto_op(@_, 1160); };
# These are not really crypto, but vcrypto_op template works
my $vaddudm = sub { vcrypto_op(@_, 192); };
my $vadduqm = sub { vcrypto_op(@_, 256); };
my $vmuleuw = sub { vcrypto_op(@_, 648); };
my $vmulouw = sub { vcrypto_op(@_, 136); };
my $vrld = sub { vcrypto_op(@_, 196); };
my $vsld = sub { vcrypto_op(@_, 1476); };
my $vsrd = sub { vcrypto_op(@_, 1732); };
my $vsubudm = sub { vcrypto_op(@_, 1216); };
my $vaddcuq = sub { vcrypto_op(@_, 320); };
my $vaddeuqm = sub { vfour(@_,60); };
my $vaddecuq = sub { vfour(@_,61); };
my $vmrgew = sub { vfour(@_,0,1932); };
my $vmrgow = sub { vfour(@_,0,1676); };
my $mtsle = sub {
my ($f, $arg) = @_;
" .long ".sprintf "0x%X",(31<<26)|($arg<<21)|(147*2);
};
# VSX instructions masqueraded as AltiVec/VMX
my $mtvrd = sub {
my ($f, $vrt, $ra) = @_;
" .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|(179<<1)|1;
};
my $mtvrwz = sub {
my ($f, $vrt, $ra) = @_;
" .long ".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|(243<<1)|1;
};
my $lvwzx_u = sub { vsxmem_op(@_, 12); }; # lxsiwzx
my $stvwx_u = sub { vsxmem_op(@_, 140); }; # stxsiwx
# PowerISA 3.0 stuff
my $maddhdu = sub { vfour(@_,49); };
my $maddld = sub { vfour(@_,51); };
my $darn = sub {
my ($f, $rt, $l) = @_;
" .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($l<<16)|(755<<1);
};
my $iseleq = sub {
my ($f, $rt, $ra, $rb) = @_;
" .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|(2<<6)|30;
};
# VSX instruction[s] masqueraded as made-up AltiVec/VMX
my $vspltib = sub { # xxspltib
my ($f, $vrt, $imm8) = @_;
$imm8 = oct($imm8) if ($imm8 =~ /^0/);
$imm8 &= 0xff;
" .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($imm8<<11)|(360<<1)|1;
};
# PowerISA 3.0B stuff
my $addex = sub {
my ($f, $rt, $ra, $rb, $cy) = @_; # only cy==0 is specified in 3.0B
" .long ".sprintf "0x%X",(31<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($cy<<9)|(170<<1);
};
my $vmsumudm = sub { vfour(@_,35); };
while($line=<>) {
$line =~ s|[#!;].*$||; # get rid of asm-style comments...
$line =~ s|/\*.*\*/||; # ... and C-style comments...
$line =~ s|^\s+||; # ... and skip white spaces in beginning...
$line =~ s|\s+$||; # ... and at the end
{
$line =~ s|\.L(\w+)|L$1|g; # common denominator for Locallabel
$line =~ s|\bL(\w+)|\.L$1|g if ($dotinlocallabels);
}
{
$line =~ s|(^[\.\w]+)\:\s*||;
my $label = $1;
if ($label) {
my $xlated = ($GLOBALS{$label} or $label);
print "$xlated:";
if ($flavour =~ /linux.*64(le|v2)/) {
if ($TYPES{$label} =~ /function/) {
printf "\n.localentry %s,0\n",$xlated;
}
}
}
}
{
$line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||;
my $c = $1; $c = "\t" if ($c eq "");
my $mnemonic = $2;
my $f = $3;
my $opcode = eval("\$$mnemonic");
$line =~ s/\b(c?[rf]|v|vs)([0-9]+)\b/$2/g if ($c ne "." and $flavour !~ /osx/);
if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(/,\s*/,$line)); }
elsif ($mnemonic) { $line = $c.$mnemonic.$f."\t".$line; }
}
print $line if ($line);
print "\n";
}
close STDOUT;

View file

@ -0,0 +1,413 @@
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov, @dot-asm, initially for use in the OpenSSL
# project. The module is dual licensed under OpenSSL and CRYPTOGAMS
# licenses depending on where you obtain it. For further details see
# https://github.com/dot-asm/cryptogams/.
# ====================================================================
# SHA256/512 for PowerISA v2.07.
#
# Accurate performance measurements are problematic, because it's
# always virtualized setup with possibly throttled processor.
# Relative comparison is therefore more informative. This module is
# ~60% faster than integer-only sha512-ppc.pl. To anchor to something
# else, SHA256 is 24% slower than sha1-ppc.pl and 2.5x slower than
# hardware-assisted aes-128-cbc encrypt. SHA512 is 20% faster than
# sha1-ppc.pl and 1.6x slower than aes-128-cbc. Another interesting
# result is degree of computational resources' utilization. POWER8 is
# "massively multi-threaded chip" and difference between single- and
# maximum multi-process benchmark results tells that utilization is
# whooping 94%. For sha512-ppc.pl we get [not unimpressive] 84% and
# for sha1-ppc.pl - 73%. 100% means that multi-process result equals
# to single-process one, given that all threads end up on the same
# physical core.
#
######################################################################
# Believed-to-be-accurate results in cycles per processed byte [on
# little-endian system]. Numbers in square brackets are for 64-bit
# build of sha512-ppc.pl, presented for reference.
#
# POWER8 POWER9
# SHA256 9.7 [15.8] 11.2 [12.5]
# SHA512 6.1 [10.3] 7.0 [7.9]
$flavour=shift;
$output =shift;
if ($flavour =~ /64/) {
$SIZE_T=8;
$LRSAVE=2*$SIZE_T;
$STU="stdu";
$POP="ld";
$PUSH="std";
} elsif ($flavour =~ /32/) {
$SIZE_T=4;
$LRSAVE=$SIZE_T;
$STU="stwu";
$POP="lwz";
$PUSH="stw";
} else { die "nonsense $flavour"; }
$LENDIAN=($flavour=~/le/);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
if ($output =~ /512/) {
$bits=512;
$SZ=8;
$sz="d";
$rounds=80;
} else {
$bits=256;
$SZ=4;
$sz="w";
$rounds=64;
}
$func="sha${bits}_block_p8";
$LOCALS=8*$SIZE_T+8*16;
$FRAME=$LOCALS+9*16+6*$SIZE_T;
$sp ="r1";
$toc="r2";
$ctx="r3";
$inp="r4";
$num="r5";
$Tbl="r6";
$idx="r7";
$lrsave="r8";
$offload="r11";
$vrsave="r12";
@I = ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70) = (0,map("r$_",(10,26..31)));
@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("v$_",(0..7));
@X=map("v$_",(8..19,24..27));
($Ki,$Func,$Sigma,$lemask)=map("v$_",(28..31));
sub ROUND {
my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
my $j=($i+1)%16;
my $k=($i+2)%8;
$code.=<<___ if ($i<15 && ($i%(16/$SZ))==(16/$SZ-1));
lvx_u @X[$i+1],0,$inp ; load X[i] in advance
addi $inp,$inp,16
___
$code.=<<___ if ($i<16 && ($i%(16/$SZ)));
vsldoi @X[$i],@X[$i-1],@X[$i-1],$SZ
___
$code.=<<___ if ($LENDIAN && $i<16 && ($i%(16/$SZ))==0);
vperm @X[$i],@X[$i],@X[$i],$lemask
___
$code.=<<___ if ($i>=15);
vshasigma${sz} $Sigma,@X[($j+1)%16],0,0
vaddu${sz}m @X[$j],@X[$j],$Sigma
vshasigma${sz} $Sigma,@X[($j+14)%16],0,15
vaddu${sz}m @X[$j],@X[$j],$Sigma
vaddu${sz}m @X[$j],@X[$j],@X[($j+9)%16]
___
$code.=<<___;
vaddu${sz}m $h,$h,@X[$i%16] ; h+=X[i]
vsel $Func,$g,$f,$e ; Ch(e,f,g)
vaddu${sz}m $g,$g,$Ki ; future h+=K[i]
vaddu${sz}m $h,$h,$Func ; h+=Ch(e,f,g)
vshasigma${sz} $Sigma,$e,1,15 ; Sigma1(e)
vaddu${sz}m $h,$h,$Sigma ; h+=Sigma1(e)
vxor $Func,$a,$b
vsel $Func,$b,$c,$Func ; Maj(a,b,c)
vaddu${sz}m $d,$d,$h ; d+=h
vshasigma${sz} $Sigma,$a,1,0 ; Sigma0(a)
vaddu${sz}m $Sigma,$Sigma,$Func ; Sigma0(a)+Maj(a,b,c)
vaddu${sz}m $h,$h,$Sigma ; h+=Sigma0(a)+Maj(a,b,c)
lvx $Ki,@I[$k],$idx ; load next K[i]
___
$code.=<<___ if ($k == 7);
addi $idx,$idx,0x80
___
}
$code=<<___;
.machine "any"
.text
.globl $func
.align 6
$func:
$STU $sp,-$FRAME($sp)
mflr $lrsave
li r10,`$LOCALS+15`
li r11,`$LOCALS+31`
stvx v24,r10,$sp # ABI says so
addi r10,r10,32
mfspr $vrsave,256
stvx v25,r11,$sp
addi r11,r11,32
stvx v26,r10,$sp
addi r10,r10,32
stvx v27,r11,$sp
addi r11,r11,32
stvx v28,r10,$sp
addi r10,r10,32
stvx v29,r11,$sp
addi r11,r11,32
stvx v30,r10,$sp
stvx v31,r11,$sp
li r11,-4096+255 # 0xfffff0ff
stw $vrsave,`$FRAME-6*$SIZE_T-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME-6*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME-5*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME-4*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME-3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME-2*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME-1*$SIZE_T`($sp)
li $x70,0x70
$PUSH $lrsave,`$FRAME+$LRSAVE`($sp)
mtspr 256,r11
bl LPICmeup
addi $offload,$sp,`8*$SIZE_T+15`
___
$code.=<<___ if ($LENDIAN);
li $idx,8
lvsl $lemask,0,$idx
vspltisb $Ki,0x0f
vxor $lemask,$lemask,$Ki
___
$code.=<<___ if ($SZ==4);
lvx_4w $A,$x00,$ctx
lvx_4w $E,$x10,$ctx
vsldoi $B,$A,$A,4 # unpack
vsldoi $C,$A,$A,8
vsldoi $D,$A,$A,12
vsldoi $F,$E,$E,4
vsldoi $G,$E,$E,8
vsldoi $H,$E,$E,12
___
$code.=<<___ if ($SZ==8);
lvx_u $A,$x00,$ctx
lvx_u $C,$x10,$ctx
lvx_u $E,$x20,$ctx
vsldoi $B,$A,$A,8 # unpack
lvx_u $G,$x30,$ctx
vsldoi $D,$C,$C,8
vsldoi $F,$E,$E,8
vsldoi $H,$G,$G,8
___
$code.=<<___;
li r0,`($rounds-16)/16` # inner loop counter
b Loop
.align 5
Loop:
lvx $Ki,$x00,$Tbl
lvx_u @X[0],0,$inp
addi $inp,$inp,16
mr $idx,$Tbl # copy $Tbl
stvx $A,$x00,$offload # offload $A-$H
stvx $B,$x10,$offload
stvx $C,$x20,$offload
stvx $D,$x30,$offload
stvx $E,$x40,$offload
stvx $F,$x50,$offload
stvx $G,$x60,$offload
stvx $H,$x70,$offload
vaddu${sz}m $H,$H,$Ki # h+K[i]
lvx $Ki,$x10,$Tbl
___
for ($i=0;$i<16;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
mtctr r0
b L16_xx
.align 5
L16_xx:
___
for (;$i<32;$i++) { &ROUND($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
bdnz L16_xx
lvx @X[2],$x00,$offload
subic. $num,$num,1
lvx @X[3],$x10,$offload
vaddu${sz}m $A,$A,@X[2]
lvx @X[4],$x20,$offload
vaddu${sz}m $B,$B,@X[3]
lvx @X[5],$x30,$offload
vaddu${sz}m $C,$C,@X[4]
lvx @X[6],$x40,$offload
vaddu${sz}m $D,$D,@X[5]
lvx @X[7],$x50,$offload
vaddu${sz}m $E,$E,@X[6]
lvx @X[8],$x60,$offload
vaddu${sz}m $F,$F,@X[7]
lvx @X[9],$x70,$offload
vaddu${sz}m $G,$G,@X[8]
vaddu${sz}m $H,$H,@X[9]
bne Loop
___
$code.=<<___ if ($SZ==4);
lvx @X[0],$x20,$idx
vperm $A,$A,$B,$Ki # pack the answer
lvx @X[1],$x30,$idx
vperm $E,$E,$F,$Ki
vperm $A,$A,$C,@X[0]
vperm $E,$E,$G,@X[0]
vperm $A,$A,$D,@X[1]
vperm $E,$E,$H,@X[1]
stvx_4w $A,$x00,$ctx
stvx_4w $E,$x10,$ctx
___
$code.=<<___ if ($SZ==8);
vperm $A,$A,$B,$Ki # pack the answer
vperm $C,$C,$D,$Ki
vperm $E,$E,$F,$Ki
vperm $G,$G,$H,$Ki
stvx_u $A,$x00,$ctx
stvx_u $C,$x10,$ctx
stvx_u $E,$x20,$ctx
stvx_u $G,$x30,$ctx
___
$code.=<<___;
addi $offload,$sp,`$LOCALS+15`
mtlr $lrsave
mtspr 256,$vrsave
lvx v24,$x00,$offload # ABI says so
lvx v25,$x10,$offload
lvx v26,$x20,$offload
lvx v27,$x30,$offload
lvx v28,$x40,$offload
lvx v29,$x50,$offload
lvx v30,$x60,$offload
lvx v31,$x70,$offload
$POP r26,`$FRAME-6*$SIZE_T`($sp)
$POP r27,`$FRAME-5*$SIZE_T`($sp)
$POP r28,`$FRAME-4*$SIZE_T`($sp)
$POP r29,`$FRAME-3*$SIZE_T`($sp)
$POP r30,`$FRAME-2*$SIZE_T`($sp)
$POP r31,`$FRAME-1*$SIZE_T`($sp)
addi $sp,$sp,$FRAME
blr
.long 0
.byte 0,12,4,1,0x80,6,3,0
.long 0
.size $func,.-$func
___
# Ugly hack here, because PPC assembler syntax seem to vary too
# much from platforms to platform...
$code.=<<___;
.align 6
LPICmeup:
mflr r0
bcl 20,31,\$+4
mflr $Tbl ; vvvvvv "distance" between . and 1st data entry
addi $Tbl,$Tbl,`64-8`
mtlr r0
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
.space `64-9*4`
___
if ($SZ==8) {
local *table = sub {
foreach(@_) { $code.=".quad $_,$_\n"; }
};
table(
"0x428a2f98d728ae22","0x7137449123ef65cd",
"0xb5c0fbcfec4d3b2f","0xe9b5dba58189dbbc",
"0x3956c25bf348b538","0x59f111f1b605d019",
"0x923f82a4af194f9b","0xab1c5ed5da6d8118",
"0xd807aa98a3030242","0x12835b0145706fbe",
"0x243185be4ee4b28c","0x550c7dc3d5ffb4e2",
"0x72be5d74f27b896f","0x80deb1fe3b1696b1",
"0x9bdc06a725c71235","0xc19bf174cf692694",
"0xe49b69c19ef14ad2","0xefbe4786384f25e3",
"0x0fc19dc68b8cd5b5","0x240ca1cc77ac9c65",
"0x2de92c6f592b0275","0x4a7484aa6ea6e483",
"0x5cb0a9dcbd41fbd4","0x76f988da831153b5",
"0x983e5152ee66dfab","0xa831c66d2db43210",
"0xb00327c898fb213f","0xbf597fc7beef0ee4",
"0xc6e00bf33da88fc2","0xd5a79147930aa725",
"0x06ca6351e003826f","0x142929670a0e6e70",
"0x27b70a8546d22ffc","0x2e1b21385c26c926",
"0x4d2c6dfc5ac42aed","0x53380d139d95b3df",
"0x650a73548baf63de","0x766a0abb3c77b2a8",
"0x81c2c92e47edaee6","0x92722c851482353b",
"0xa2bfe8a14cf10364","0xa81a664bbc423001",
"0xc24b8b70d0f89791","0xc76c51a30654be30",
"0xd192e819d6ef5218","0xd69906245565a910",
"0xf40e35855771202a","0x106aa07032bbd1b8",
"0x19a4c116b8d2d0c8","0x1e376c085141ab53",
"0x2748774cdf8eeb99","0x34b0bcb5e19b48a8",
"0x391c0cb3c5c95a63","0x4ed8aa4ae3418acb",
"0x5b9cca4f7763e373","0x682e6ff3d6b2b8a3",
"0x748f82ee5defb2fc","0x78a5636f43172f60",
"0x84c87814a1f0ab72","0x8cc702081a6439ec",
"0x90befffa23631e28","0xa4506cebde82bde9",
"0xbef9a3f7b2c67915","0xc67178f2e372532b",
"0xca273eceea26619c","0xd186b8c721c0c207",
"0xeada7dd6cde0eb1e","0xf57d4f7fee6ed178",
"0x06f067aa72176fba","0x0a637dc5a2c898a6",
"0x113f9804bef90dae","0x1b710b35131c471b",
"0x28db77f523047d84","0x32caab7b40c72493",
"0x3c9ebe0a15c9bebc","0x431d67c49c100d4c",
"0x4cc5d4becb3e42b6","0x597f299cfc657e2a",
"0x5fcb6fab3ad6faec","0x6c44198c4a475817","0");
$code.=<<___ if (!$LENDIAN);
.quad 0x0001020304050607,0x1011121314151617
___
$code.=<<___ if ($LENDIAN); # quad-swapped
.quad 0x1011121314151617,0x0001020304050607
___
} else {
local *table = sub {
foreach(@_) { $code.=".long $_,$_,$_,$_\n"; }
};
table(
"0x428a2f98","0x71374491","0xb5c0fbcf","0xe9b5dba5",
"0x3956c25b","0x59f111f1","0x923f82a4","0xab1c5ed5",
"0xd807aa98","0x12835b01","0x243185be","0x550c7dc3",
"0x72be5d74","0x80deb1fe","0x9bdc06a7","0xc19bf174",
"0xe49b69c1","0xefbe4786","0x0fc19dc6","0x240ca1cc",
"0x2de92c6f","0x4a7484aa","0x5cb0a9dc","0x76f988da",
"0x983e5152","0xa831c66d","0xb00327c8","0xbf597fc7",
"0xc6e00bf3","0xd5a79147","0x06ca6351","0x14292967",
"0x27b70a85","0x2e1b2138","0x4d2c6dfc","0x53380d13",
"0x650a7354","0x766a0abb","0x81c2c92e","0x92722c85",
"0xa2bfe8a1","0xa81a664b","0xc24b8b70","0xc76c51a3",
"0xd192e819","0xd6990624","0xf40e3585","0x106aa070",
"0x19a4c116","0x1e376c08","0x2748774c","0x34b0bcb5",
"0x391c0cb3","0x4ed8aa4a","0x5b9cca4f","0x682e6ff3",
"0x748f82ee","0x78a5636f","0x84c87814","0x8cc70208",
"0x90befffa","0xa4506ceb","0xbef9a3f7","0xc67178f2","0");
$code.=<<___ if (!$LENDIAN);
.long 0x00010203,0x10111213,0x10111213,0x10111213
.long 0x00010203,0x04050607,0x10111213,0x10111213
.long 0x00010203,0x04050607,0x08090a0b,0x10111213
___
$code.=<<___ if ($LENDIAN); # word-swapped
.long 0x10111213,0x10111213,0x10111213,0x00010203
.long 0x10111213,0x10111213,0x04050607,0x00010203
.long 0x10111213,0x08090a0b,0x04050607,0x00010203
___
}
$code.=<<___;
.asciz "SHA${bits} for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
print $code;
close STDOUT;

View file

@ -0,0 +1,28 @@
#include "blapi.h"
#include "mpi.h"
#include "mpprime.h"
mp_err
mpp_random_secure(mp_int *a)
{
SECStatus rv;
rv = RNG_GenerateGlobalRandomBytes((unsigned char *)MP_DIGITS(a), MP_USED(a) * sizeof(mp_digit));
if (rv != SECSuccess) {
return MP_UNDEF;
}
MP_SIGN(a) = MP_ZPOS;
return MP_OKAY;
}
mp_err
mpp_pprime_secure(mp_int *a, int nt)
{
return mpp_pprime_ext_random(a, nt, &mpp_random_secure);
}
mp_err
mpp_make_prime_secure(mp_int *start, mp_size nBits, mp_size strong)
{
return mpp_make_prime_ext_random(start, nBits, strong, &mpp_random_secure);
}

View file

@ -52,3 +52,12 @@
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); \
break; \
}
/* Fill the `used` digits of an mp_int with random bits */
mp_err mpp_random_secure(mp_int *a);
/* Pseudo-primality testing using `mpp_random_secure` to choose Miller-Rabin base */
mp_err mpp_pprime_secure(mp_int *a, int nt);
/* Variant of `mpp_make_prime` using `mpp_random_secure` to choose Miller-Rabin base */
mp_err mpp_make_prime_secure(mp_int *start, mp_size nBits, mp_size strong);

View file

@ -0,0 +1,264 @@
/* 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 USE_HW_SHA1
#ifndef __ARM_FEATURE_CRYPTO
#error "Compiler option is invalid"
#endif
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include <arm_neon.h>
#include <memory.h>
#include "blapi.h"
#include "sha_fast.h"
#if !defined(SHA_PUT_W_IN_STACK)
#define H2X 11
#else
#define H2X 0
#endif
static void shaCompress(SHA_HW_t *X, const PRUint32 *datain);
void
SHA1_Compress_Native(SHA1Context *ctx)
{
shaCompress(&ctx->H[H2X], ctx->u.w);
}
/*
* SHA: Add data to context.
*/
void
SHA1_Update_Native(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
{
unsigned int lenB;
unsigned int togo;
if (!len) {
return;
}
/* accumulate the byte count. */
lenB = (unsigned int)(ctx->size) & 63U;
ctx->size += len;
/*
* Read the data into W and process blocks as they get full
*/
if (lenB > 0) {
togo = 64U - lenB;
if (len < togo) {
togo = len;
}
memcpy(ctx->u.b + lenB, dataIn, togo);
len -= togo;
dataIn += togo;
lenB = (lenB + togo) & 63U;
if (!lenB) {
shaCompress(&ctx->H[H2X], ctx->u.w);
}
}
while (len >= 64U) {
len -= 64U;
shaCompress(&ctx->H[H2X], (PRUint32 *)dataIn);
dataIn += 64U;
}
if (len) {
memcpy(ctx->u.b, dataIn, len);
}
}
/*
* SHA: Compression function, unrolled.
*/
static void
shaCompress(SHA_HW_t *X, const PRUint32 *inbuf)
{
#define XH(n) X[n - H2X]
const uint32x4_t K0 = vdupq_n_u32(0x5a827999);
const uint32x4_t K1 = vdupq_n_u32(0x6ed9eba1);
const uint32x4_t K2 = vdupq_n_u32(0x8f1bbcdc);
const uint32x4_t K3 = vdupq_n_u32(0xca62c1d6);
uint32x4_t abcd = vld1q_u32(&XH(0));
PRUint32 e = XH(4);
const uint32x4_t origABCD = abcd;
const PRUint32 origE = e;
uint32x4_t w0 = vld1q_u32(inbuf);
uint32x4_t w1 = vld1q_u32(inbuf + 4);
uint32x4_t w2 = vld1q_u32(inbuf + 8);
uint32x4_t w3 = vld1q_u32(inbuf + 12);
w0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(w0)));
w1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(w1)));
w2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(w2)));
w3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(w3)));
uint32x4_t t0 = vaddq_u32(w0, K0);
uint32x4_t t1 = vaddq_u32(w1, K0);
PRUint32 tmpE;
/*
* Using the following ARM instructions to accelerate SHA1
*
* sha1c for round 0 - 20
* sha1p for round 20 - 40
* sha1m for round 40 - 60
* sha1p for round 60 - 80
* sha1su0 and shasu1 for message schedule
* sha1h for rotate left 30
*/
/* Round 0-3 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1cq_u32(abcd, e, t0);
t0 = vaddq_u32(w2, K0);
w0 = vsha1su0q_u32(w0, w1, w2);
/* Round 4-7 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1cq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w3, K0);
w0 = vsha1su1q_u32(w0, w3);
w1 = vsha1su0q_u32(w1, w2, w3);
/* Round 8-11 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1cq_u32(abcd, e, t0);
t0 = vaddq_u32(w0, K0);
w1 = vsha1su1q_u32(w1, w0);
w2 = vsha1su0q_u32(w2, w3, w0);
/* Round 12-15 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1cq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w1, K1);
w2 = vsha1su1q_u32(w2, w1);
w3 = vsha1su0q_u32(w3, w0, w1);
/* Round 16-19 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1cq_u32(abcd, e, t0);
t0 = vaddq_u32(w2, K1);
w3 = vsha1su1q_u32(w3, w2);
w0 = vsha1su0q_u32(w0, w1, w2);
/* Round 20-23 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w3, K1);
w0 = vsha1su1q_u32(w0, w3);
w1 = vsha1su0q_u32(w1, w2, w3);
/* Round 24-27 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, e, t0);
t0 = vaddq_u32(w0, K1);
w1 = vsha1su1q_u32(w1, w0);
w2 = vsha1su0q_u32(w2, w3, w0);
/* Round 28-31 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w1, K1);
w2 = vsha1su1q_u32(w2, w1);
w3 = vsha1su0q_u32(w3, w0, w1);
/* Round 32-35 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, e, t0);
t0 = vaddq_u32(w2, K2);
w3 = vsha1su1q_u32(w3, w2);
w0 = vsha1su0q_u32(w0, w1, w2);
/* Round 36-39 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w3, K2);
w0 = vsha1su1q_u32(w0, w3);
w1 = vsha1su0q_u32(w1, w2, w3);
/* Round 40-43 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1mq_u32(abcd, e, t0);
t0 = vaddq_u32(w0, K2);
w1 = vsha1su1q_u32(w1, w0);
w2 = vsha1su0q_u32(w2, w3, w0);
/* Round 44-47 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1mq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w1, K2);
w2 = vsha1su1q_u32(w2, w1);
w3 = vsha1su0q_u32(w3, w0, w1);
/* Round 48-51 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1mq_u32(abcd, e, t0);
t0 = vaddq_u32(w2, K2);
w3 = vsha1su1q_u32(w3, w2);
w0 = vsha1su0q_u32(w0, w1, w2);
/* Round 52-55 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1mq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w3, K3);
w0 = vsha1su1q_u32(w0, w3);
w1 = vsha1su0q_u32(w1, w2, w3);
/* Round 56-59 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1mq_u32(abcd, e, t0);
t0 = vaddq_u32(w0, K3);
w1 = vsha1su1q_u32(w1, w0);
w2 = vsha1su0q_u32(w2, w3, w0);
/* Round 60-63 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w1, K3);
w2 = vsha1su1q_u32(w2, w1);
w3 = vsha1su0q_u32(w3, w0, w1);
/* Round 64-67 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, e, t0);
t0 = vaddq_u32(w2, K3);
w3 = vsha1su1q_u32(w3, w2);
w0 = vsha1su0q_u32(w0, w1, w2);
/* Round 68-71 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
t1 = vaddq_u32(w3, K3);
w0 = vsha1su1q_u32(w0, w3);
/* Round 72-75 */
tmpE = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, e, t0);
/* Round 76-79 */
e = vsha1h_u32(vgetq_lane_u32(abcd, 0));
abcd = vsha1pq_u32(abcd, tmpE, t1);
e += origE;
abcd = vaddq_u32(origABCD, abcd);
vst1q_u32(&XH(0), abcd);
XH(4) = e;
}
#endif /* USE_HW_SHA1 */

View file

@ -0,0 +1,203 @@
/* 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 USE_HW_SHA2
#ifndef __ARM_FEATURE_CRYPTO
#error "Compiler option is invalid"
#endif
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "prcpucfg.h"
#include "prtypes.h" /* for PRUintXX */
#include "prlong.h"
#include "blapi.h"
#include "sha256.h"
#include <arm_neon.h>
/* SHA-256 constants, K256. */
static const PRUint32 __attribute__((aligned(16))) K256[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#define ROUND(n, a, b, c, d) \
{ \
uint32x4_t t = vaddq_u32(a, k##n); \
uint32x4_t wt = w0; \
w0 = vsha256hq_u32(w0, w1, t); \
w1 = vsha256h2q_u32(w1, wt, t); \
if (n < 12) { \
a = vsha256su0q_u32(a, b); \
a = vsha256su1q_u32(a, c, d); \
} \
}
void
SHA256_Compress_Native(SHA256Context *ctx)
{
const uint32x4_t k0 = vld1q_u32(K256);
const uint32x4_t k1 = vld1q_u32(K256 + 4);
const uint32x4_t k2 = vld1q_u32(K256 + 8);
const uint32x4_t k3 = vld1q_u32(K256 + 12);
const uint32x4_t k4 = vld1q_u32(K256 + 16);
const uint32x4_t k5 = vld1q_u32(K256 + 20);
const uint32x4_t k6 = vld1q_u32(K256 + 24);
const uint32x4_t k7 = vld1q_u32(K256 + 28);
const uint32x4_t k8 = vld1q_u32(K256 + 32);
const uint32x4_t k9 = vld1q_u32(K256 + 36);
const uint32x4_t k10 = vld1q_u32(K256 + 40);
const uint32x4_t k11 = vld1q_u32(K256 + 44);
const uint32x4_t k12 = vld1q_u32(K256 + 48);
const uint32x4_t k13 = vld1q_u32(K256 + 52);
const uint32x4_t k14 = vld1q_u32(K256 + 56);
const uint32x4_t k15 = vld1q_u32(K256 + 60);
uint32x4_t h0 = vld1q_u32(ctx->h);
uint32x4_t h1 = vld1q_u32(ctx->h + 4);
unsigned char *input = ctx->u.b;
uint32x4_t a = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input)));
uint32x4_t b = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 16)));
uint32x4_t c = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 32)));
uint32x4_t d = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 48)));
uint32x4_t w0 = h0;
uint32x4_t w1 = h1;
ROUND(0, a, b, c, d)
ROUND(1, b, c, d, a)
ROUND(2, c, d, a, b)
ROUND(3, d, a, b, c)
ROUND(4, a, b, c, d)
ROUND(5, b, c, d, a)
ROUND(6, c, d, a, b)
ROUND(7, d, a, b, c)
ROUND(8, a, b, c, d)
ROUND(9, b, c, d, a)
ROUND(10, c, d, a, b)
ROUND(11, d, a, b, c)
ROUND(12, a, b, c, d)
ROUND(13, b, c, d, a)
ROUND(14, c, d, a, b)
ROUND(15, d, a, b, c)
h0 = vaddq_u32(h0, w0);
h1 = vaddq_u32(h1, w1);
vst1q_u32(ctx->h, h0);
vst1q_u32(ctx->h + 4, h1);
}
void
SHA256_Update_Native(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
const uint32x4_t k0 = vld1q_u32(K256);
const uint32x4_t k1 = vld1q_u32(K256 + 4);
const uint32x4_t k2 = vld1q_u32(K256 + 8);
const uint32x4_t k3 = vld1q_u32(K256 + 12);
const uint32x4_t k4 = vld1q_u32(K256 + 16);
const uint32x4_t k5 = vld1q_u32(K256 + 20);
const uint32x4_t k6 = vld1q_u32(K256 + 24);
const uint32x4_t k7 = vld1q_u32(K256 + 28);
const uint32x4_t k8 = vld1q_u32(K256 + 32);
const uint32x4_t k9 = vld1q_u32(K256 + 36);
const uint32x4_t k10 = vld1q_u32(K256 + 40);
const uint32x4_t k11 = vld1q_u32(K256 + 44);
const uint32x4_t k12 = vld1q_u32(K256 + 48);
const uint32x4_t k13 = vld1q_u32(K256 + 52);
const uint32x4_t k14 = vld1q_u32(K256 + 56);
const uint32x4_t k15 = vld1q_u32(K256 + 60);
unsigned int inBuf = ctx->sizeLo & 0x3f;
if (!inputLen) {
return;
}
/* Add inputLen into the count of bytes processed, before processing */
if ((ctx->sizeLo += inputLen) < inputLen) {
ctx->sizeHi++;
}
/* if data already in buffer, attemp to fill rest of buffer */
if (inBuf) {
unsigned int todo = SHA256_BLOCK_LENGTH - inBuf;
if (inputLen < todo) {
todo = inputLen;
}
memcpy(ctx->u.b + inBuf, input, todo);
input += todo;
inputLen -= todo;
if (inBuf + todo == SHA256_BLOCK_LENGTH) {
SHA256_Compress_Native(ctx);
}
}
uint32x4_t h0 = vld1q_u32(ctx->h);
uint32x4_t h1 = vld1q_u32(ctx->h + 4);
/* if enough data to fill one or more whole buffers, process them. */
while (inputLen >= SHA256_BLOCK_LENGTH) {
uint32x4_t a, b, c, d;
a = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input)));
b = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 16)));
c = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 32)));
d = vreinterpretq_u32_u8(vrev32q_u8(vld1q_u8(input + 48)));
input += SHA256_BLOCK_LENGTH;
inputLen -= SHA256_BLOCK_LENGTH;
uint32x4_t w0 = h0;
uint32x4_t w1 = h1;
ROUND(0, a, b, c, d)
ROUND(1, b, c, d, a)
ROUND(2, c, d, a, b)
ROUND(3, d, a, b, c)
ROUND(4, a, b, c, d)
ROUND(5, b, c, d, a)
ROUND(6, c, d, a, b)
ROUND(7, d, a, b, c)
ROUND(8, a, b, c, d)
ROUND(9, b, c, d, a)
ROUND(10, c, d, a, b)
ROUND(11, d, a, b, c)
ROUND(12, a, b, c, d)
ROUND(13, b, c, d, a)
ROUND(14, c, d, a, b)
ROUND(15, d, a, b, c)
h0 = vaddq_u32(h0, w0);
h1 = vaddq_u32(h1, w1);
}
vst1q_u32(ctx->h, h0);
vst1q_u32(ctx->h + 4, h1);
/* if data left over, fill it into buffer */
if (inputLen) {
memcpy(ctx->u.b, input, inputLen);
}
}
#endif /* USE_HW_SHA2 */

View file

@ -0,0 +1,236 @@
/* 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 USE_HW_SHA2
#include <immintrin.h>
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "blapii.h"
#include "prcpucfg.h"
#include "prtypes.h" /* for PRUintXX */
#include "prlong.h"
#include "blapi.h"
#include "sha256.h"
/* SHA-256 constants, K256. */
pre_align static const PRUint32 K256[64] post_align = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
#define ROUND(n, a, b, c, d) \
{ \
__m128i t = _mm_add_epi32(a, k##n); \
w1 = _mm_sha256rnds2_epu32(w1, w0, t); \
t = _mm_shuffle_epi32(t, 0x0e); \
w0 = _mm_sha256rnds2_epu32(w0, w1, t); \
if (n < 12) { \
a = _mm_sha256msg1_epu32(a, b); \
a = _mm_add_epi32(a, _mm_alignr_epi8(d, c, 4)); \
a = _mm_sha256msg2_epu32(a, d); \
} \
}
void
SHA256_Compress_Native(SHA256Context *ctx)
{
__m128i h0, h1, th;
__m128i a, b, c, d;
__m128i w0, w1;
const __m128i shuffle = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
const __m128i *K = (__m128i *)K256;
const __m128i k0 = _mm_load_si128(K);
const __m128i k1 = _mm_load_si128(K + 1);
const __m128i k2 = _mm_load_si128(K + 2);
const __m128i k3 = _mm_load_si128(K + 3);
const __m128i k4 = _mm_load_si128(K + 4);
const __m128i k5 = _mm_load_si128(K + 5);
const __m128i k6 = _mm_load_si128(K + 6);
const __m128i k7 = _mm_load_si128(K + 7);
const __m128i k8 = _mm_load_si128(K + 8);
const __m128i k9 = _mm_load_si128(K + 9);
const __m128i k10 = _mm_load_si128(K + 10);
const __m128i k11 = _mm_load_si128(K + 11);
const __m128i k12 = _mm_load_si128(K + 12);
const __m128i k13 = _mm_load_si128(K + 13);
const __m128i k14 = _mm_load_si128(K + 14);
const __m128i k15 = _mm_load_si128(K + 15);
const __m128i *input = (__m128i *)ctx->u.b;
h0 = _mm_loadu_si128((__m128i *)(ctx->h));
h1 = _mm_loadu_si128((__m128i *)(ctx->h + 4));
/* H0123:4567 -> H01256:H2367 */
th = _mm_shuffle_epi32(h0, 0xb1);
h1 = _mm_shuffle_epi32(h1, 0x1b);
h0 = _mm_alignr_epi8(th, h1, 8);
h1 = _mm_blend_epi16(h1, th, 0xf0);
a = _mm_shuffle_epi8(_mm_loadu_si128(input), shuffle);
b = _mm_shuffle_epi8(_mm_loadu_si128(input + 1), shuffle);
c = _mm_shuffle_epi8(_mm_loadu_si128(input + 2), shuffle);
d = _mm_shuffle_epi8(_mm_loadu_si128(input + 3), shuffle);
w0 = h0;
w1 = h1;
ROUND(0, a, b, c, d)
ROUND(1, b, c, d, a)
ROUND(2, c, d, a, b)
ROUND(3, d, a, b, c)
ROUND(4, a, b, c, d)
ROUND(5, b, c, d, a)
ROUND(6, c, d, a, b)
ROUND(7, d, a, b, c)
ROUND(8, a, b, c, d)
ROUND(9, b, c, d, a)
ROUND(10, c, d, a, b)
ROUND(11, d, a, b, c)
ROUND(12, a, b, c, d)
ROUND(13, b, c, d, a)
ROUND(14, c, d, a, b)
ROUND(15, d, a, b, c)
h0 = _mm_add_epi32(h0, w0);
h1 = _mm_add_epi32(h1, w1);
/* H0145:2367 -> H0123:4567 */
th = _mm_shuffle_epi32(h0, 0x1b);
h1 = _mm_shuffle_epi32(h1, 0xb1);
h0 = _mm_blend_epi16(th, h1, 0xf0);
h1 = _mm_alignr_epi8(h1, th, 8);
_mm_storeu_si128((__m128i *)ctx->h, h0);
_mm_storeu_si128((__m128i *)(ctx->h + 4), h1);
}
void
SHA256_Update_Native(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
__m128i h0, h1, th;
const __m128i shuffle = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
const __m128i *K = (__m128i *)K256;
const __m128i k0 = _mm_load_si128(K);
const __m128i k1 = _mm_load_si128(K + 1);
const __m128i k2 = _mm_load_si128(K + 2);
const __m128i k3 = _mm_load_si128(K + 3);
const __m128i k4 = _mm_load_si128(K + 4);
const __m128i k5 = _mm_load_si128(K + 5);
const __m128i k6 = _mm_load_si128(K + 6);
const __m128i k7 = _mm_load_si128(K + 7);
const __m128i k8 = _mm_load_si128(K + 8);
const __m128i k9 = _mm_load_si128(K + 9);
const __m128i k10 = _mm_load_si128(K + 10);
const __m128i k11 = _mm_load_si128(K + 11);
const __m128i k12 = _mm_load_si128(K + 12);
const __m128i k13 = _mm_load_si128(K + 13);
const __m128i k14 = _mm_load_si128(K + 14);
const __m128i k15 = _mm_load_si128(K + 15);
unsigned int inBuf = ctx->sizeLo & 0x3f;
if (!inputLen) {
return;
}
/* Add inputLen into the count of bytes processed, before processing */
if ((ctx->sizeLo += inputLen) < inputLen) {
ctx->sizeHi++;
}
/* if data already in buffer, attempt to fill rest of buffer */
if (inBuf) {
unsigned int todo = SHA256_BLOCK_LENGTH - inBuf;
if (inputLen < todo) {
todo = inputLen;
}
memcpy(ctx->u.b + inBuf, input, todo);
input += todo;
inputLen -= todo;
if (inBuf + todo == SHA256_BLOCK_LENGTH) {
SHA256_Compress_Native(ctx);
}
}
h0 = _mm_loadu_si128((__m128i *)(ctx->h));
h1 = _mm_loadu_si128((__m128i *)(ctx->h + 4));
/* H0123:4567 -> H01256:H2367 */
th = _mm_shuffle_epi32(h0, 0xb1);
h1 = _mm_shuffle_epi32(h1, 0x1b);
h0 = _mm_alignr_epi8(th, h1, 8);
h1 = _mm_blend_epi16(h1, th, 0xf0);
/* if enough data to fill one or more whole buffers, process them. */
while (inputLen >= SHA256_BLOCK_LENGTH) {
__m128i a, b, c, d;
__m128i w0, w1;
a = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)input), shuffle);
b = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)(input + 16)), shuffle);
c = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)(input + 32)), shuffle);
d = _mm_shuffle_epi8(_mm_loadu_si128((__m128i *)(input + 48)), shuffle);
input += SHA256_BLOCK_LENGTH;
inputLen -= SHA256_BLOCK_LENGTH;
w0 = h0;
w1 = h1;
ROUND(0, a, b, c, d)
ROUND(1, b, c, d, a)
ROUND(2, c, d, a, b)
ROUND(3, d, a, b, c)
ROUND(4, a, b, c, d)
ROUND(5, b, c, d, a)
ROUND(6, c, d, a, b)
ROUND(7, d, a, b, c)
ROUND(8, a, b, c, d)
ROUND(9, b, c, d, a)
ROUND(10, c, d, a, b)
ROUND(11, d, a, b, c)
ROUND(12, a, b, c, d)
ROUND(13, b, c, d, a)
ROUND(14, c, d, a, b)
ROUND(15, d, a, b, c)
h0 = _mm_add_epi32(h0, w0);
h1 = _mm_add_epi32(h1, w1);
}
// H01234567 -> H01256 and H2367
th = _mm_shuffle_epi32(h0, 0x1b);
h1 = _mm_shuffle_epi32(h1, 0xb1);
h0 = _mm_blend_epi16(th, h1, 0xf0);
h1 = _mm_alignr_epi8(h1, th, 8);
_mm_storeu_si128((__m128i *)ctx->h, h0);
_mm_storeu_si128((__m128i *)(ctx->h + 4), h1);
/* if data left over, fill it into buffer */
if (inputLen) {
memcpy(ctx->u.b, input, inputLen);
}
}
#endif /* USE_HW_SHA2 */

View file

@ -7,6 +7,12 @@
#include "prtypes.h"
struct SHA256ContextStr;
typedef void (*sha256_compress_t)(struct SHA256ContextStr *);
typedef void (*sha256_update_t)(struct SHA256ContextStr *, const unsigned char *,
unsigned int);
struct SHA256ContextStr {
union {
PRUint32 w[64]; /* message schedule, input buffer, plus 48 words */
@ -14,6 +20,8 @@ struct SHA256ContextStr {
} u;
PRUint32 h[8]; /* 8 state variables */
PRUint32 sizeHi, sizeLo; /* 64-bit count of hashed bytes. */
sha256_compress_t compress;
sha256_update_t update;
};
#endif /* _SHA_256_H_ */

View file

@ -0,0 +1,851 @@
# Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
# All rights reserved.
# See the full LICENSE under scripts/.
.machine "any"
.abiversion 2
.text
.globl sha512_block_p8
.type sha512_block_p8,@function
.align 6
sha512_block_p8:
.localentry sha512_block_p8,0
stdu 1,-384(1)
mflr 8
li 10,207
li 11,223
stvx 24,10,1
addi 10,10,32
li 12,-1
stvx 25,11,1
addi 11,11,32
stvx 26,10,1
addi 10,10,32
stvx 27,11,1
addi 11,11,32
stvx 28,10,1
addi 10,10,32
stvx 29,11,1
addi 11,11,32
stvx 30,10,1
stvx 31,11,1
li 11,-4096+255
stw 12,332(1)
li 10,0x10
std 26,336(1)
li 26,0x20
std 27,344(1)
li 27,0x30
std 28,352(1)
li 28,0x40
std 29,360(1)
li 29,0x50
std 30,368(1)
li 30,0x60
std 31,376(1)
li 31,0x70
std 8,400(1)
or 11,11,11
bl .LPICmeup
addi 11,1,79
li 7,8
lvsl 31,0,7
vspltisb 28,0x0f
vxor 31,31,28
.long 0x7C001E99
.long 0x7C4A1E99
.long 0x7C9A1E99
vsldoi 1,0,0,8
.long 0x7CDB1E99
vsldoi 3,2,2,8
vsldoi 5,4,4,8
vsldoi 7,6,6,8
li 0,4
b .Loop
.align 5
.Loop:
lvx 28,0,6
.long 0x7D002699
addi 4,4,16
mr 7,6
stvx 0,0,11
stvx 1,10,11
stvx 2,26,11
stvx 3,27,11
stvx 4,28,11
stvx 5,29,11
stvx 6,30,11
stvx 7,31,11
.long 0x10E7E0C0
lvx 28,10,6
vperm 8,8,8,31
.long 0x10E740C0
vsel 29,6,5,4
.long 0x10C6E0C0
.long 0x10E7E8C0
.long 0x13C4FEC2
.long 0x10E7F0C0
vxor 29,0,1
vsel 29,1,2,29
.long 0x106338C0
.long 0x13C086C2
.long 0x13DEE8C0
.long 0x10E7F0C0
lvx 28,26,7
.long 0x7D402699
addi 4,4,16
vsldoi 9,8,8,8
.long 0x10C648C0
vsel 29,5,4,3
.long 0x10A5E0C0
.long 0x10C6E8C0
.long 0x13C3FEC2
.long 0x10C6F0C0
vxor 29,7,0
vsel 29,0,1,29
.long 0x104230C0
.long 0x13C786C2
.long 0x13DEE8C0
.long 0x10C6F0C0
lvx 28,27,7
vperm 10,10,10,31
.long 0x10A550C0
vsel 29,4,3,2
.long 0x1084E0C0
.long 0x10A5E8C0
.long 0x13C2FEC2
.long 0x10A5F0C0
vxor 29,6,7
vsel 29,7,0,29
.long 0x102128C0
.long 0x13C686C2
.long 0x13DEE8C0
.long 0x10A5F0C0
lvx 28,28,7
.long 0x7D802699
addi 4,4,16
vsldoi 11,10,10,8
.long 0x108458C0
vsel 29,3,2,1
.long 0x1063E0C0
.long 0x1084E8C0
.long 0x13C1FEC2
.long 0x1084F0C0
vxor 29,5,6
vsel 29,6,7,29
.long 0x100020C0
.long 0x13C586C2
.long 0x13DEE8C0
.long 0x1084F0C0
lvx 28,29,7
vperm 12,12,12,31
.long 0x106360C0
vsel 29,2,1,0
.long 0x1042E0C0
.long 0x1063E8C0
.long 0x13C0FEC2
.long 0x1063F0C0
vxor 29,4,5
vsel 29,5,6,29
.long 0x10E718C0
.long 0x13C486C2
.long 0x13DEE8C0
.long 0x1063F0C0
lvx 28,30,7
.long 0x7DC02699
addi 4,4,16
vsldoi 13,12,12,8
.long 0x104268C0
vsel 29,1,0,7
.long 0x1021E0C0
.long 0x1042E8C0
.long 0x13C7FEC2
.long 0x1042F0C0
vxor 29,3,4
vsel 29,4,5,29
.long 0x10C610C0
.long 0x13C386C2
.long 0x13DEE8C0
.long 0x1042F0C0
lvx 28,31,7
addi 7,7,0x80
vperm 14,14,14,31
.long 0x102170C0
vsel 29,0,7,6
.long 0x1000E0C0
.long 0x1021E8C0
.long 0x13C6FEC2
.long 0x1021F0C0
vxor 29,2,3
vsel 29,3,4,29
.long 0x10A508C0
.long 0x13C286C2
.long 0x13DEE8C0
.long 0x1021F0C0
lvx 28,0,7
.long 0x7E002699
addi 4,4,16
vsldoi 15,14,14,8
.long 0x100078C0
vsel 29,7,6,5
.long 0x10E7E0C0
.long 0x1000E8C0
.long 0x13C5FEC2
.long 0x1000F0C0
vxor 29,1,2
vsel 29,2,3,29
.long 0x108400C0
.long 0x13C186C2
.long 0x13DEE8C0
.long 0x1000F0C0
lvx 28,10,7
vperm 16,16,16,31
.long 0x10E780C0
vsel 29,6,5,4
.long 0x10C6E0C0
.long 0x10E7E8C0
.long 0x13C4FEC2
.long 0x10E7F0C0
vxor 29,0,1
vsel 29,1,2,29
.long 0x106338C0
.long 0x13C086C2
.long 0x13DEE8C0
.long 0x10E7F0C0
lvx 28,26,7
.long 0x7E402699
addi 4,4,16
vsldoi 17,16,16,8
.long 0x10C688C0
vsel 29,5,4,3
.long 0x10A5E0C0
.long 0x10C6E8C0
.long 0x13C3FEC2
.long 0x10C6F0C0
vxor 29,7,0
vsel 29,0,1,29
.long 0x104230C0
.long 0x13C786C2
.long 0x13DEE8C0
.long 0x10C6F0C0
lvx 28,27,7
vperm 18,18,18,31
.long 0x10A590C0
vsel 29,4,3,2
.long 0x1084E0C0
.long 0x10A5E8C0
.long 0x13C2FEC2
.long 0x10A5F0C0
vxor 29,6,7
vsel 29,7,0,29
.long 0x102128C0
.long 0x13C686C2
.long 0x13DEE8C0
.long 0x10A5F0C0
lvx 28,28,7
.long 0x7F002699
addi 4,4,16
vsldoi 19,18,18,8
.long 0x108498C0
vsel 29,3,2,1
.long 0x1063E0C0
.long 0x1084E8C0
.long 0x13C1FEC2
.long 0x1084F0C0
vxor 29,5,6
vsel 29,6,7,29
.long 0x100020C0
.long 0x13C586C2
.long 0x13DEE8C0
.long 0x1084F0C0
lvx 28,29,7
vperm 24,24,24,31
.long 0x1063C0C0
vsel 29,2,1,0
.long 0x1042E0C0
.long 0x1063E8C0
.long 0x13C0FEC2
.long 0x1063F0C0
vxor 29,4,5
vsel 29,5,6,29
.long 0x10E718C0
.long 0x13C486C2
.long 0x13DEE8C0
.long 0x1063F0C0
lvx 28,30,7
.long 0x7F402699
addi 4,4,16
vsldoi 25,24,24,8
.long 0x1042C8C0
vsel 29,1,0,7
.long 0x1021E0C0
.long 0x1042E8C0
.long 0x13C7FEC2
.long 0x1042F0C0
vxor 29,3,4
vsel 29,4,5,29
.long 0x10C610C0
.long 0x13C386C2
.long 0x13DEE8C0
.long 0x1042F0C0
lvx 28,31,7
addi 7,7,0x80
vperm 26,26,26,31
.long 0x1021D0C0
vsel 29,0,7,6
.long 0x1000E0C0
.long 0x1021E8C0
.long 0x13C6FEC2
.long 0x1021F0C0
vxor 29,2,3
vsel 29,3,4,29
.long 0x10A508C0
.long 0x13C286C2
.long 0x13DEE8C0
.long 0x1021F0C0
lvx 28,0,7
vsldoi 27,26,26,8
.long 0x13C906C2
.long 0x1108F0C0
.long 0x13DA7EC2
.long 0x1108F0C0
.long 0x110888C0
.long 0x1000D8C0
vsel 29,7,6,5
.long 0x10E7E0C0
.long 0x1000E8C0
.long 0x13C5FEC2
.long 0x1000F0C0
vxor 29,1,2
vsel 29,2,3,29
.long 0x108400C0
.long 0x13C186C2
.long 0x13DEE8C0
.long 0x1000F0C0
lvx 28,10,7
mtctr 0
b .L16_xx
.align 5
.L16_xx:
.long 0x13CA06C2
.long 0x1129F0C0
.long 0x13DB7EC2
.long 0x1129F0C0
.long 0x112990C0
.long 0x10E740C0
vsel 29,6,5,4
.long 0x10C6E0C0
.long 0x10E7E8C0
.long 0x13C4FEC2
.long 0x10E7F0C0
vxor 29,0,1
vsel 29,1,2,29
.long 0x106338C0
.long 0x13C086C2
.long 0x13DEE8C0
.long 0x10E7F0C0
lvx 28,26,7
.long 0x13CB06C2
.long 0x114AF0C0
.long 0x13C87EC2
.long 0x114AF0C0
.long 0x114A98C0
.long 0x10C648C0
vsel 29,5,4,3
.long 0x10A5E0C0
.long 0x10C6E8C0
.long 0x13C3FEC2
.long 0x10C6F0C0
vxor 29,7,0
vsel 29,0,1,29
.long 0x104230C0
.long 0x13C786C2
.long 0x13DEE8C0
.long 0x10C6F0C0
lvx 28,27,7
.long 0x13CC06C2
.long 0x116BF0C0
.long 0x13C97EC2
.long 0x116BF0C0
.long 0x116BC0C0
.long 0x10A550C0
vsel 29,4,3,2
.long 0x1084E0C0
.long 0x10A5E8C0
.long 0x13C2FEC2
.long 0x10A5F0C0
vxor 29,6,7
vsel 29,7,0,29
.long 0x102128C0
.long 0x13C686C2
.long 0x13DEE8C0
.long 0x10A5F0C0
lvx 28,28,7
.long 0x13CD06C2
.long 0x118CF0C0
.long 0x13CA7EC2
.long 0x118CF0C0
.long 0x118CC8C0
.long 0x108458C0
vsel 29,3,2,1
.long 0x1063E0C0
.long 0x1084E8C0
.long 0x13C1FEC2
.long 0x1084F0C0
vxor 29,5,6
vsel 29,6,7,29
.long 0x100020C0
.long 0x13C586C2
.long 0x13DEE8C0
.long 0x1084F0C0
lvx 28,29,7
.long 0x13CE06C2
.long 0x11ADF0C0
.long 0x13CB7EC2
.long 0x11ADF0C0
.long 0x11ADD0C0
.long 0x106360C0
vsel 29,2,1,0
.long 0x1042E0C0
.long 0x1063E8C0
.long 0x13C0FEC2
.long 0x1063F0C0
vxor 29,4,5
vsel 29,5,6,29
.long 0x10E718C0
.long 0x13C486C2
.long 0x13DEE8C0
.long 0x1063F0C0
lvx 28,30,7
.long 0x13CF06C2
.long 0x11CEF0C0
.long 0x13CC7EC2
.long 0x11CEF0C0
.long 0x11CED8C0
.long 0x104268C0
vsel 29,1,0,7
.long 0x1021E0C0
.long 0x1042E8C0
.long 0x13C7FEC2
.long 0x1042F0C0
vxor 29,3,4
vsel 29,4,5,29
.long 0x10C610C0
.long 0x13C386C2
.long 0x13DEE8C0
.long 0x1042F0C0
lvx 28,31,7
addi 7,7,0x80
.long 0x13D006C2
.long 0x11EFF0C0
.long 0x13CD7EC2
.long 0x11EFF0C0
.long 0x11EF40C0
.long 0x102170C0
vsel 29,0,7,6
.long 0x1000E0C0
.long 0x1021E8C0
.long 0x13C6FEC2
.long 0x1021F0C0
vxor 29,2,3
vsel 29,3,4,29
.long 0x10A508C0
.long 0x13C286C2
.long 0x13DEE8C0
.long 0x1021F0C0
lvx 28,0,7
.long 0x13D106C2
.long 0x1210F0C0
.long 0x13CE7EC2
.long 0x1210F0C0
.long 0x121048C0
.long 0x100078C0
vsel 29,7,6,5
.long 0x10E7E0C0
.long 0x1000E8C0
.long 0x13C5FEC2
.long 0x1000F0C0
vxor 29,1,2
vsel 29,2,3,29
.long 0x108400C0
.long 0x13C186C2
.long 0x13DEE8C0
.long 0x1000F0C0
lvx 28,10,7
.long 0x13D206C2
.long 0x1231F0C0
.long 0x13CF7EC2
.long 0x1231F0C0
.long 0x123150C0
.long 0x10E780C0
vsel 29,6,5,4
.long 0x10C6E0C0
.long 0x10E7E8C0
.long 0x13C4FEC2
.long 0x10E7F0C0
vxor 29,0,1
vsel 29,1,2,29
.long 0x106338C0
.long 0x13C086C2
.long 0x13DEE8C0
.long 0x10E7F0C0
lvx 28,26,7
.long 0x13D306C2
.long 0x1252F0C0
.long 0x13D07EC2
.long 0x1252F0C0
.long 0x125258C0
.long 0x10C688C0
vsel 29,5,4,3
.long 0x10A5E0C0
.long 0x10C6E8C0
.long 0x13C3FEC2
.long 0x10C6F0C0
vxor 29,7,0
vsel 29,0,1,29
.long 0x104230C0
.long 0x13C786C2
.long 0x13DEE8C0
.long 0x10C6F0C0
lvx 28,27,7
.long 0x13D806C2
.long 0x1273F0C0
.long 0x13D17EC2
.long 0x1273F0C0
.long 0x127360C0
.long 0x10A590C0
vsel 29,4,3,2
.long 0x1084E0C0
.long 0x10A5E8C0
.long 0x13C2FEC2
.long 0x10A5F0C0
vxor 29,6,7
vsel 29,7,0,29
.long 0x102128C0
.long 0x13C686C2
.long 0x13DEE8C0
.long 0x10A5F0C0
lvx 28,28,7
.long 0x13D906C2
.long 0x1318F0C0
.long 0x13D27EC2
.long 0x1318F0C0
.long 0x131868C0
.long 0x108498C0
vsel 29,3,2,1
.long 0x1063E0C0
.long 0x1084E8C0
.long 0x13C1FEC2
.long 0x1084F0C0
vxor 29,5,6
vsel 29,6,7,29
.long 0x100020C0
.long 0x13C586C2
.long 0x13DEE8C0
.long 0x1084F0C0
lvx 28,29,7
.long 0x13DA06C2
.long 0x1339F0C0
.long 0x13D37EC2
.long 0x1339F0C0
.long 0x133970C0
.long 0x1063C0C0
vsel 29,2,1,0
.long 0x1042E0C0
.long 0x1063E8C0
.long 0x13C0FEC2
.long 0x1063F0C0
vxor 29,4,5
vsel 29,5,6,29
.long 0x10E718C0
.long 0x13C486C2
.long 0x13DEE8C0
.long 0x1063F0C0
lvx 28,30,7
.long 0x13DB06C2
.long 0x135AF0C0
.long 0x13D87EC2
.long 0x135AF0C0
.long 0x135A78C0
.long 0x1042C8C0
vsel 29,1,0,7
.long 0x1021E0C0
.long 0x1042E8C0
.long 0x13C7FEC2
.long 0x1042F0C0
vxor 29,3,4
vsel 29,4,5,29
.long 0x10C610C0
.long 0x13C386C2
.long 0x13DEE8C0
.long 0x1042F0C0
lvx 28,31,7
addi 7,7,0x80
.long 0x13C806C2
.long 0x137BF0C0
.long 0x13D97EC2
.long 0x137BF0C0
.long 0x137B80C0
.long 0x1021D0C0
vsel 29,0,7,6
.long 0x1000E0C0
.long 0x1021E8C0
.long 0x13C6FEC2
.long 0x1021F0C0
vxor 29,2,3
vsel 29,3,4,29
.long 0x10A508C0
.long 0x13C286C2
.long 0x13DEE8C0
.long 0x1021F0C0
lvx 28,0,7
.long 0x13C906C2
.long 0x1108F0C0
.long 0x13DA7EC2
.long 0x1108F0C0
.long 0x110888C0
.long 0x1000D8C0
vsel 29,7,6,5
.long 0x10E7E0C0
.long 0x1000E8C0
.long 0x13C5FEC2
.long 0x1000F0C0
vxor 29,1,2
vsel 29,2,3,29
.long 0x108400C0
.long 0x13C186C2
.long 0x13DEE8C0
.long 0x1000F0C0
lvx 28,10,7
bdnz .L16_xx
lvx 10,0,11
subic. 5,5,1
lvx 11,10,11
.long 0x100050C0
lvx 12,26,11
.long 0x102158C0
lvx 13,27,11
.long 0x104260C0
lvx 14,28,11
.long 0x106368C0
lvx 15,29,11
.long 0x108470C0
lvx 16,30,11
.long 0x10A578C0
lvx 17,31,11
.long 0x10C680C0
.long 0x10E788C0
bne .Loop
vperm 0,0,1,28
vperm 2,2,3,28
vperm 4,4,5,28
vperm 6,6,7,28
.long 0x7C001F99
.long 0x7C4A1F99
.long 0x7C9A1F99
.long 0x7CDB1F99
addi 11,1,207
mtlr 8
or 12,12,12
lvx 24,0,11
lvx 25,10,11
lvx 26,26,11
lvx 27,27,11
lvx 28,28,11
lvx 29,29,11
lvx 30,30,11
lvx 31,31,11
ld 26,336(1)
ld 27,344(1)
ld 28,352(1)
ld 29,360(1)
ld 30,368(1)
ld 31,376(1)
addi 1,1,384
blr
.long 0
.byte 0,12,4,1,0x80,6,3,0
.long 0
.size sha512_block_p8,.-sha512_block_p8
.align 6
.LPICmeup:
mflr 0
bcl 20,31,$+4
mflr 6
addi 6,6,56
mtlr 0
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
.space 28
.long 0xd728ae22,0x428a2f98
.long 0xd728ae22,0x428a2f98
.long 0x23ef65cd,0x71374491
.long 0x23ef65cd,0x71374491
.long 0xec4d3b2f,0xb5c0fbcf
.long 0xec4d3b2f,0xb5c0fbcf
.long 0x8189dbbc,0xe9b5dba5
.long 0x8189dbbc,0xe9b5dba5
.long 0xf348b538,0x3956c25b
.long 0xf348b538,0x3956c25b
.long 0xb605d019,0x59f111f1
.long 0xb605d019,0x59f111f1
.long 0xaf194f9b,0x923f82a4
.long 0xaf194f9b,0x923f82a4
.long 0xda6d8118,0xab1c5ed5
.long 0xda6d8118,0xab1c5ed5
.long 0xa3030242,0xd807aa98
.long 0xa3030242,0xd807aa98
.long 0x45706fbe,0x12835b01
.long 0x45706fbe,0x12835b01
.long 0x4ee4b28c,0x243185be
.long 0x4ee4b28c,0x243185be
.long 0xd5ffb4e2,0x550c7dc3
.long 0xd5ffb4e2,0x550c7dc3
.long 0xf27b896f,0x72be5d74
.long 0xf27b896f,0x72be5d74
.long 0x3b1696b1,0x80deb1fe
.long 0x3b1696b1,0x80deb1fe
.long 0x25c71235,0x9bdc06a7
.long 0x25c71235,0x9bdc06a7
.long 0xcf692694,0xc19bf174
.long 0xcf692694,0xc19bf174
.long 0x9ef14ad2,0xe49b69c1
.long 0x9ef14ad2,0xe49b69c1
.long 0x384f25e3,0xefbe4786
.long 0x384f25e3,0xefbe4786
.long 0x8b8cd5b5,0x0fc19dc6
.long 0x8b8cd5b5,0x0fc19dc6
.long 0x77ac9c65,0x240ca1cc
.long 0x77ac9c65,0x240ca1cc
.long 0x592b0275,0x2de92c6f
.long 0x592b0275,0x2de92c6f
.long 0x6ea6e483,0x4a7484aa
.long 0x6ea6e483,0x4a7484aa
.long 0xbd41fbd4,0x5cb0a9dc
.long 0xbd41fbd4,0x5cb0a9dc
.long 0x831153b5,0x76f988da
.long 0x831153b5,0x76f988da
.long 0xee66dfab,0x983e5152
.long 0xee66dfab,0x983e5152
.long 0x2db43210,0xa831c66d
.long 0x2db43210,0xa831c66d
.long 0x98fb213f,0xb00327c8
.long 0x98fb213f,0xb00327c8
.long 0xbeef0ee4,0xbf597fc7
.long 0xbeef0ee4,0xbf597fc7
.long 0x3da88fc2,0xc6e00bf3
.long 0x3da88fc2,0xc6e00bf3
.long 0x930aa725,0xd5a79147
.long 0x930aa725,0xd5a79147
.long 0xe003826f,0x06ca6351
.long 0xe003826f,0x06ca6351
.long 0x0a0e6e70,0x14292967
.long 0x0a0e6e70,0x14292967
.long 0x46d22ffc,0x27b70a85
.long 0x46d22ffc,0x27b70a85
.long 0x5c26c926,0x2e1b2138
.long 0x5c26c926,0x2e1b2138
.long 0x5ac42aed,0x4d2c6dfc
.long 0x5ac42aed,0x4d2c6dfc
.long 0x9d95b3df,0x53380d13
.long 0x9d95b3df,0x53380d13
.long 0x8baf63de,0x650a7354
.long 0x8baf63de,0x650a7354
.long 0x3c77b2a8,0x766a0abb
.long 0x3c77b2a8,0x766a0abb
.long 0x47edaee6,0x81c2c92e
.long 0x47edaee6,0x81c2c92e
.long 0x1482353b,0x92722c85
.long 0x1482353b,0x92722c85
.long 0x4cf10364,0xa2bfe8a1
.long 0x4cf10364,0xa2bfe8a1
.long 0xbc423001,0xa81a664b
.long 0xbc423001,0xa81a664b
.long 0xd0f89791,0xc24b8b70
.long 0xd0f89791,0xc24b8b70
.long 0x0654be30,0xc76c51a3
.long 0x0654be30,0xc76c51a3
.long 0xd6ef5218,0xd192e819
.long 0xd6ef5218,0xd192e819
.long 0x5565a910,0xd6990624
.long 0x5565a910,0xd6990624
.long 0x5771202a,0xf40e3585
.long 0x5771202a,0xf40e3585
.long 0x32bbd1b8,0x106aa070
.long 0x32bbd1b8,0x106aa070
.long 0xb8d2d0c8,0x19a4c116
.long 0xb8d2d0c8,0x19a4c116
.long 0x5141ab53,0x1e376c08
.long 0x5141ab53,0x1e376c08
.long 0xdf8eeb99,0x2748774c
.long 0xdf8eeb99,0x2748774c
.long 0xe19b48a8,0x34b0bcb5
.long 0xe19b48a8,0x34b0bcb5
.long 0xc5c95a63,0x391c0cb3
.long 0xc5c95a63,0x391c0cb3
.long 0xe3418acb,0x4ed8aa4a
.long 0xe3418acb,0x4ed8aa4a
.long 0x7763e373,0x5b9cca4f
.long 0x7763e373,0x5b9cca4f
.long 0xd6b2b8a3,0x682e6ff3
.long 0xd6b2b8a3,0x682e6ff3
.long 0x5defb2fc,0x748f82ee
.long 0x5defb2fc,0x748f82ee
.long 0x43172f60,0x78a5636f
.long 0x43172f60,0x78a5636f
.long 0xa1f0ab72,0x84c87814
.long 0xa1f0ab72,0x84c87814
.long 0x1a6439ec,0x8cc70208
.long 0x1a6439ec,0x8cc70208
.long 0x23631e28,0x90befffa
.long 0x23631e28,0x90befffa
.long 0xde82bde9,0xa4506ceb
.long 0xde82bde9,0xa4506ceb
.long 0xb2c67915,0xbef9a3f7
.long 0xb2c67915,0xbef9a3f7
.long 0xe372532b,0xc67178f2
.long 0xe372532b,0xc67178f2
.long 0xea26619c,0xca273ece
.long 0xea26619c,0xca273ece
.long 0x21c0c207,0xd186b8c7
.long 0x21c0c207,0xd186b8c7
.long 0xcde0eb1e,0xeada7dd6
.long 0xcde0eb1e,0xeada7dd6
.long 0xee6ed178,0xf57d4f7f
.long 0xee6ed178,0xf57d4f7f
.long 0x72176fba,0x06f067aa
.long 0x72176fba,0x06f067aa
.long 0xa2c898a6,0x0a637dc5
.long 0xa2c898a6,0x0a637dc5
.long 0xbef90dae,0x113f9804
.long 0xbef90dae,0x113f9804
.long 0x131c471b,0x1b710b35
.long 0x131c471b,0x1b710b35
.long 0x23047d84,0x28db77f5
.long 0x23047d84,0x28db77f5
.long 0x40c72493,0x32caab7b
.long 0x40c72493,0x32caab7b
.long 0x15c9bebc,0x3c9ebe0a
.long 0x15c9bebc,0x3c9ebe0a
.long 0x9c100d4c,0x431d67c4
.long 0x9c100d4c,0x431d67c4
.long 0xcb3e42b6,0x4cc5d4be
.long 0xcb3e42b6,0x4cc5d4be
.long 0xfc657e2a,0x597f299c
.long 0xfc657e2a,0x597f299c
.long 0x3ad6faec,0x5fcb6fab
.long 0x3ad6faec,0x5fcb6fab
.long 0x4a475817,0x6c44198c
.long 0x4a475817,0x6c44198c
.long 0,0
.long 0,0
.long 0x14151617,0x10111213
.long 0x04050607,0x00010203
.byte 83,72,65,53,49,50,32,102,111,114,32,80,111,119,101,114,73,83,65,32,50,46,48,55,44,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
.align 2
.align 2

View file

@ -18,8 +18,11 @@
#include "prlong.h"
#include "secport.h" /* for PORT_XXX */
#include "blapi.h"
#include "blapii.h"
#include "secerr.h"
#include "sha256.h" /* for struct SHA256ContextStr */
#include "crypto_primitives.h"
#include "ppc-crypto.h" /* for USE_PPC_CRYPTO */
/* ============= Common constants and defines ======================= */
@ -43,7 +46,7 @@ static const PRUint8 pad[240] = {
/* ============= SHA256 implementation ================================== */
/* SHA-256 constants, K256. */
static const PRUint32 K256[64] = {
pre_align static const PRUint32 K256[64] post_align = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@ -154,6 +157,30 @@ swap4b(PRUint32 value)
#define s0(x) (ROTR32(x, 7) ^ ROTR32(x, 18) ^ SHR(x, 3))
#define s1(x) (ROTR32(x, 17) ^ ROTR32(x, 19) ^ SHR(x, 10))
void SHA256_Compress_Native(SHA256Context *ctx);
void SHA256_Update_Native(SHA256Context *ctx, const unsigned char *input, unsigned int inputLen);
static void SHA256_Compress_Generic(SHA256Context *ctx);
static void SHA256_Update_Generic(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen);
#if !defined(USE_HW_SHA2)
void
SHA256_Compress_Native(SHA256Context *ctx)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
void
SHA256_Update_Native(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
#endif
SHA256Context *
SHA256_NewContext(void)
{
@ -173,13 +200,181 @@ SHA256_DestroyContext(SHA256Context *ctx, PRBool freeit)
void
SHA256_Begin(SHA256Context *ctx)
{
PRBool use_hw_sha2 = PR_FALSE;
memset(ctx, 0, sizeof *ctx);
memcpy(H, H256, sizeof H256);
#if defined(USE_HW_SHA2) && defined(IS_LITTLE_ENDIAN)
/* arm's implementation is tested on little endian only */
use_hw_sha2 = arm_sha2_support() || (sha_support() && ssse3_support() && sse4_1_support());
#endif
if (use_hw_sha2) {
ctx->compress = SHA256_Compress_Native;
ctx->update = SHA256_Update_Native;
} else {
ctx->compress = SHA256_Compress_Generic;
ctx->update = SHA256_Update_Generic;
}
}
#if defined(USE_PPC_CRYPTO)
#define ROUND(n, a, b, c, d, e, f, g, h) \
s0 = __builtin_crypto_vshasigmaw(e, 1, 0xf); \
h += s0 + vec_sel(g, f, e) + w[n / 4]; \
d += h; \
s0 = __builtin_crypto_vshasigmaw(a, 1, 0); \
h += s0 + vec_sel(b, c, vec_xor(a, b)); \
if (n % 4 != 3) \
w[n / 4] = vec_sro(w[n / 4], rshift);
#else
#define ROUND(n, a, b, c, d, e, f, g, h) \
h += S1(e) + Ch(e, f, g) + K256[n] + W[n]; \
d += h; \
h += S0(a) + Maj(a, b, c);
#endif
#define SHA256_UNROLLED_ROUNDS \
ROUND(0, a, b, c, d, e, f, g, h) \
ROUND(1, h, a, b, c, d, e, f, g) \
ROUND(2, g, h, a, b, c, d, e, f) \
ROUND(3, f, g, h, a, b, c, d, e) \
ROUND(4, e, f, g, h, a, b, c, d) \
ROUND(5, d, e, f, g, h, a, b, c) \
ROUND(6, c, d, e, f, g, h, a, b) \
ROUND(7, b, c, d, e, f, g, h, a) \
\
ROUND(8, a, b, c, d, e, f, g, h) \
ROUND(9, h, a, b, c, d, e, f, g) \
ROUND(10, g, h, a, b, c, d, e, f) \
ROUND(11, f, g, h, a, b, c, d, e) \
ROUND(12, e, f, g, h, a, b, c, d) \
ROUND(13, d, e, f, g, h, a, b, c) \
ROUND(14, c, d, e, f, g, h, a, b) \
ROUND(15, b, c, d, e, f, g, h, a) \
\
ROUND(16, a, b, c, d, e, f, g, h) \
ROUND(17, h, a, b, c, d, e, f, g) \
ROUND(18, g, h, a, b, c, d, e, f) \
ROUND(19, f, g, h, a, b, c, d, e) \
ROUND(20, e, f, g, h, a, b, c, d) \
ROUND(21, d, e, f, g, h, a, b, c) \
ROUND(22, c, d, e, f, g, h, a, b) \
ROUND(23, b, c, d, e, f, g, h, a) \
\
ROUND(24, a, b, c, d, e, f, g, h) \
ROUND(25, h, a, b, c, d, e, f, g) \
ROUND(26, g, h, a, b, c, d, e, f) \
ROUND(27, f, g, h, a, b, c, d, e) \
ROUND(28, e, f, g, h, a, b, c, d) \
ROUND(29, d, e, f, g, h, a, b, c) \
ROUND(30, c, d, e, f, g, h, a, b) \
ROUND(31, b, c, d, e, f, g, h, a) \
\
ROUND(32, a, b, c, d, e, f, g, h) \
ROUND(33, h, a, b, c, d, e, f, g) \
ROUND(34, g, h, a, b, c, d, e, f) \
ROUND(35, f, g, h, a, b, c, d, e) \
ROUND(36, e, f, g, h, a, b, c, d) \
ROUND(37, d, e, f, g, h, a, b, c) \
ROUND(38, c, d, e, f, g, h, a, b) \
ROUND(39, b, c, d, e, f, g, h, a) \
\
ROUND(40, a, b, c, d, e, f, g, h) \
ROUND(41, h, a, b, c, d, e, f, g) \
ROUND(42, g, h, a, b, c, d, e, f) \
ROUND(43, f, g, h, a, b, c, d, e) \
ROUND(44, e, f, g, h, a, b, c, d) \
ROUND(45, d, e, f, g, h, a, b, c) \
ROUND(46, c, d, e, f, g, h, a, b) \
ROUND(47, b, c, d, e, f, g, h, a) \
\
ROUND(48, a, b, c, d, e, f, g, h) \
ROUND(49, h, a, b, c, d, e, f, g) \
ROUND(50, g, h, a, b, c, d, e, f) \
ROUND(51, f, g, h, a, b, c, d, e) \
ROUND(52, e, f, g, h, a, b, c, d) \
ROUND(53, d, e, f, g, h, a, b, c) \
ROUND(54, c, d, e, f, g, h, a, b) \
ROUND(55, b, c, d, e, f, g, h, a) \
\
ROUND(56, a, b, c, d, e, f, g, h) \
ROUND(57, h, a, b, c, d, e, f, g) \
ROUND(58, g, h, a, b, c, d, e, f) \
ROUND(59, f, g, h, a, b, c, d, e) \
ROUND(60, e, f, g, h, a, b, c, d) \
ROUND(61, d, e, f, g, h, a, b, c) \
ROUND(62, c, d, e, f, g, h, a, b) \
ROUND(63, b, c, d, e, f, g, h, a)
static void
SHA256_Compress(SHA256Context *ctx)
SHA256_Compress_Generic(SHA256Context *ctx)
{
#if defined(USE_PPC_CRYPTO)
vec_u32 w[16], s0, s1;
const vec_u8 rshift = (vec_u8)vec_splats(4 << 3);
const vec_u8 shifthalf = (vec_u8)vec_splats(8 << 3);
const vec_u8 bswap4 = (vec_u8){
3, 2, 1, 0, 7, 6, 5, 4, 11,
10, 9, 8, 15, 14, 13, 12
};
unsigned i;
for (i = 0; i < 4; i++) {
w[i] = vec_vsx_ld(0, &W[i * 4]);
w[i] = vec_perm(w[i], w[i], bswap4);
}
/* prepare the message schedule */
for (i = 4; i < 16; i++) {
vec_u32 off1 = vec_sld(w[i - 3], w[i - 4], 12);
vec_u32 off2 = vec_sld(w[i - 1], w[i - 2], 12);
s0 = __builtin_crypto_vshasigmaw(off1, 0, 0);
/* first half, s1 depends on two prior ints */
s1 = __builtin_crypto_vshasigmaw(w[i - 1], 0, 0xf);
s1 = vec_sro(s1, shifthalf);
w[i] = w[i - 4] + s0 + off2 + s1;
/* second half s1 */
s1 = __builtin_crypto_vshasigmaw(w[i], 0, 0xf);
s1 = vec_slo(s1, shifthalf);
w[i] += s1;
}
for (i = 0; i < 16; i++) {
w[i] += vec_ld(0, &K256[i * 4]);
}
vec_u32 a, b, c, d, e, f, g, h;
a = vec_splats(H[0]);
b = vec_splats(H[1]);
c = vec_splats(H[2]);
d = vec_splats(H[3]);
e = vec_splats(H[4]);
f = vec_splats(H[5]);
g = vec_splats(H[6]);
h = vec_splats(H[7]);
SHA256_UNROLLED_ROUNDS;
H[0] += a[0];
H[1] += b[0];
H[2] += c[0];
H[3] += d[0];
H[4] += e[0];
H[5] += f[0];
H[6] += g[0];
H[7] += h[0];
#undef ROUND
#else /* USE_PPC_CRYPTO*/
{
#if defined(IS_LITTLE_ENDIAN)
BYTESWAP4(W[0]);
@ -280,11 +475,6 @@ SHA256_Compress(SHA256Context *ctx)
g = H[6];
h = H[7];
#define ROUND(n, a, b, c, d, e, f, g, h) \
h += S1(e) + Ch(e, f, g) + K256[n] + W[n]; \
d += h; \
h += S0(a) + Maj(a, b, c);
#ifdef NOUNROLL256
{
int t;
@ -300,77 +490,7 @@ SHA256_Compress(SHA256Context *ctx)
}
}
#else
ROUND(0, a, b, c, d, e, f, g, h)
ROUND(1, h, a, b, c, d, e, f, g)
ROUND(2, g, h, a, b, c, d, e, f)
ROUND(3, f, g, h, a, b, c, d, e)
ROUND(4, e, f, g, h, a, b, c, d)
ROUND(5, d, e, f, g, h, a, b, c)
ROUND(6, c, d, e, f, g, h, a, b)
ROUND(7, b, c, d, e, f, g, h, a)
ROUND(8, a, b, c, d, e, f, g, h)
ROUND(9, h, a, b, c, d, e, f, g)
ROUND(10, g, h, a, b, c, d, e, f)
ROUND(11, f, g, h, a, b, c, d, e)
ROUND(12, e, f, g, h, a, b, c, d)
ROUND(13, d, e, f, g, h, a, b, c)
ROUND(14, c, d, e, f, g, h, a, b)
ROUND(15, b, c, d, e, f, g, h, a)
ROUND(16, a, b, c, d, e, f, g, h)
ROUND(17, h, a, b, c, d, e, f, g)
ROUND(18, g, h, a, b, c, d, e, f)
ROUND(19, f, g, h, a, b, c, d, e)
ROUND(20, e, f, g, h, a, b, c, d)
ROUND(21, d, e, f, g, h, a, b, c)
ROUND(22, c, d, e, f, g, h, a, b)
ROUND(23, b, c, d, e, f, g, h, a)
ROUND(24, a, b, c, d, e, f, g, h)
ROUND(25, h, a, b, c, d, e, f, g)
ROUND(26, g, h, a, b, c, d, e, f)
ROUND(27, f, g, h, a, b, c, d, e)
ROUND(28, e, f, g, h, a, b, c, d)
ROUND(29, d, e, f, g, h, a, b, c)
ROUND(30, c, d, e, f, g, h, a, b)
ROUND(31, b, c, d, e, f, g, h, a)
ROUND(32, a, b, c, d, e, f, g, h)
ROUND(33, h, a, b, c, d, e, f, g)
ROUND(34, g, h, a, b, c, d, e, f)
ROUND(35, f, g, h, a, b, c, d, e)
ROUND(36, e, f, g, h, a, b, c, d)
ROUND(37, d, e, f, g, h, a, b, c)
ROUND(38, c, d, e, f, g, h, a, b)
ROUND(39, b, c, d, e, f, g, h, a)
ROUND(40, a, b, c, d, e, f, g, h)
ROUND(41, h, a, b, c, d, e, f, g)
ROUND(42, g, h, a, b, c, d, e, f)
ROUND(43, f, g, h, a, b, c, d, e)
ROUND(44, e, f, g, h, a, b, c, d)
ROUND(45, d, e, f, g, h, a, b, c)
ROUND(46, c, d, e, f, g, h, a, b)
ROUND(47, b, c, d, e, f, g, h, a)
ROUND(48, a, b, c, d, e, f, g, h)
ROUND(49, h, a, b, c, d, e, f, g)
ROUND(50, g, h, a, b, c, d, e, f)
ROUND(51, f, g, h, a, b, c, d, e)
ROUND(52, e, f, g, h, a, b, c, d)
ROUND(53, d, e, f, g, h, a, b, c)
ROUND(54, c, d, e, f, g, h, a, b)
ROUND(55, b, c, d, e, f, g, h, a)
ROUND(56, a, b, c, d, e, f, g, h)
ROUND(57, h, a, b, c, d, e, f, g)
ROUND(58, g, h, a, b, c, d, e, f)
ROUND(59, f, g, h, a, b, c, d, e)
ROUND(60, e, f, g, h, a, b, c, d)
ROUND(61, d, e, f, g, h, a, b, c)
ROUND(62, c, d, e, f, g, h, a, b)
ROUND(63, b, c, d, e, f, g, h, a)
SHA256_UNROLLED_ROUNDS;
#endif
H[0] += a;
@ -383,6 +503,7 @@ SHA256_Compress(SHA256Context *ctx)
H[7] += h;
}
#undef ROUND
#endif /* !USE_PPC_CRYPTO */
}
#undef s0
@ -393,6 +514,13 @@ SHA256_Compress(SHA256Context *ctx)
void
SHA256_Update(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
ctx->update(ctx, input, inputLen);
}
static void
SHA256_Update_Generic(SHA256Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
unsigned int inBuf = ctx->sizeLo & 0x3f;
if (!inputLen)
@ -411,7 +539,7 @@ SHA256_Update(SHA256Context *ctx, const unsigned char *input,
input += todo;
inputLen -= todo;
if (inBuf + todo == SHA256_BLOCK_LENGTH)
SHA256_Compress(ctx);
SHA256_Compress_Generic(ctx);
}
/* if enough data to fill one or more whole buffers, process them. */
@ -419,7 +547,7 @@ SHA256_Update(SHA256Context *ctx, const unsigned char *input,
memcpy(B, input, SHA256_BLOCK_LENGTH);
input += SHA256_BLOCK_LENGTH;
inputLen -= SHA256_BLOCK_LENGTH;
SHA256_Compress(ctx);
SHA256_Compress_Generic(ctx);
}
/* if data left over, fill it into buffer */
if (inputLen)
@ -437,7 +565,7 @@ SHA256_End(SHA256Context *ctx, unsigned char *digest,
hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29);
lo = (ctx->sizeLo << 3);
SHA256_Update(ctx, pad, padLen);
ctx->update(ctx, pad, padLen);
#if defined(IS_LITTLE_ENDIAN)
W[14] = SHA_HTONL(hi);
@ -446,7 +574,7 @@ SHA256_End(SHA256Context *ctx, unsigned char *digest,
W[14] = hi;
W[15] = lo;
#endif
SHA256_Compress(ctx);
ctx->compress(ctx);
/* now output the answer */
#if defined(IS_LITTLE_ENDIAN)
@ -568,15 +696,32 @@ SHA224_DestroyContext(SHA224Context *ctx, PRBool freeit)
void
SHA224_Begin(SHA224Context *ctx)
{
PRBool use_hw_sha2;
memset(ctx, 0, sizeof *ctx);
memcpy(H, H224, sizeof H224);
#if defined(USE_HW_SHA2) && defined(IS_LITTLE_ENDIAN)
/* arm's implementation is tested on little endian only */
use_hw_sha2 = arm_sha2_support() || (sha_support() && ssse3_support() && sse4_1_support());
#else
use_hw_sha2 = PR_FALSE;
#endif
if (use_hw_sha2) {
ctx->compress = SHA256_Compress_Native;
ctx->update = SHA256_Update_Native;
} else {
ctx->compress = SHA256_Compress_Generic;
ctx->update = SHA256_Update_Generic;
}
}
void
SHA224_Update(SHA224Context *ctx, const unsigned char *input,
unsigned int inputLen)
{
SHA256_Update(ctx, input, inputLen);
ctx->update(ctx, input, inputLen);
}
void
@ -691,6 +836,11 @@ SHA224_Clone(SHA224Context *dest, SHA224Context *src)
#endif
#if defined(USE_PPC_CRYPTO)
void sha512_block_p8(void *ctx, const void *inp, size_t len);
#else /* USE_PPC_CRYPTO */
/* SHA-384 and SHA-512 constants, K512. */
static const PRUint64 K512[80] = {
#if PR_BYTES_PER_LONG == 8
@ -778,6 +928,8 @@ static const PRUint64 K512[80] = {
#endif
};
#endif /* !USE_PPC_CRYPTO */
struct SHA512ContextStr {
union {
PRUint64 w[80]; /* message schedule, input buffer, plus 64 words */
@ -932,6 +1084,10 @@ SHA512_Begin(SHA512Context *ctx)
static void
SHA512_Compress(SHA512Context *ctx)
{
#if defined(USE_PPC_CRYPTO)
sha512_block_p8(&H[0], &W[0], 1);
#else /* USE_PPC_CRYPTO */
#if defined(IS_LITTLE_ENDIAN)
{
BYTESWAP8(W[0]);
@ -1174,6 +1330,8 @@ SHA512_Compress(SHA512Context *ctx)
ADDTO(g, H[6]);
ADDTO(h, H[7]);
}
#endif /* !USE_PPC_CRYPTO */
}
void

View file

@ -10,6 +10,7 @@
#include "blapi.h"
#include "sha_fast.h"
#include "prerror.h"
#include "secerr.h"
#ifdef TRACING_SSL
#include "ssl.h"
@ -28,6 +29,28 @@ static void shaCompress(volatile SHA_HW_t *X, const PRUint32 *datain);
#define SHA_MIX(n, a, b, c) XW(n) = SHA_ROTL(XW(a) ^ XW(b) ^ XW(c) ^ XW(n), 1)
void SHA1_Compress_Native(SHA1Context *ctx);
void SHA1_Update_Native(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len);
static void SHA1_Compress_Generic(SHA1Context *ctx);
static void SHA1_Update_Generic(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len);
#ifndef USE_HW_SHA1
void
SHA1_Compress_Native(SHA1Context *ctx)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
void
SHA1_Update_Native(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
{
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
PORT_Assert(0);
}
#endif
/*
* SHA: initialize context
*/
@ -43,6 +66,18 @@ SHA1_Begin(SHA1Context *ctx)
ctx->H[2] = 0x98badcfeL;
ctx->H[3] = 0x10325476L;
ctx->H[4] = 0xc3d2e1f0L;
#if defined(USE_HW_SHA1) && defined(IS_LITTLE_ENDIAN)
/* arm's implementation is tested on little endian only */
if (arm_sha1_support()) {
ctx->compress = SHA1_Compress_Native;
ctx->update = SHA1_Update_Native;
} else
#endif
{
ctx->compress = SHA1_Compress_Generic;
ctx->update = SHA1_Update_Generic;
}
}
/* Explanation of H array and index values:
@ -88,6 +123,12 @@ SHA1_Begin(SHA1Context *ctx)
*/
void
SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
{
ctx->update(ctx, dataIn, len);
}
static void
SHA1_Update_Generic(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len)
{
register unsigned int lenB;
register unsigned int togo;
@ -166,7 +207,7 @@ SHA1_End(SHA1Context *ctx, unsigned char *hashout,
size <<= 3;
ctx->W[14] = SHA_HTONL((PRUint32)(size >> 32));
ctx->W[15] = SHA_HTONL((PRUint32)size);
shaCompress(&ctx->H[H2X], ctx->W);
ctx->compress(ctx);
/*
* Output hash
@ -460,6 +501,12 @@ shaCompress(volatile SHA_HW_t *X, const PRUint32 *inbuf)
XH(4) += E;
}
static void
SHA1_Compress_Generic(SHA1Context *ctx)
{
shaCompress(&ctx->H[H2X], ctx->u.w);
}
/*************************************************************************
** Code below this line added to make SHA code support BLAPI interface
*/
@ -491,7 +538,7 @@ SHA1_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
unsigned int outLen;
SHA1_Begin(&ctx);
SHA1_Update(&ctx, src, src_length);
ctx.update(&ctx, src, src_length);
SHA1_End(&ctx, dest, &outLen, SHA1_LENGTH);
memset(&ctx, 0, sizeof ctx);
return SECSuccess;

View file

@ -10,13 +10,19 @@
#define SHA1_INPUT_LEN 64
#if defined(IS_64) && !defined(__sparc)
#if defined(IS_64) && !defined(__sparc) && !defined(__aarch64__)
typedef PRUint64 SHA_HW_t;
#define SHA1_USING_64_BIT 1
#else
typedef PRUint32 SHA_HW_t;
#endif
struct SHA1ContextStr;
typedef void (*sha1_compress_t)(struct SHA1ContextStr *);
typedef void (*sha1_update_t)(struct SHA1ContextStr *, const unsigned char *,
unsigned int);
struct SHA1ContextStr {
union {
PRUint32 w[16]; /* input buffer */
@ -24,6 +30,8 @@ struct SHA1ContextStr {
} u;
PRUint64 size; /* count of hashed bytes. */
SHA_HW_t H[22]; /* 5 state variables, 16 tmp values, 1 extra */
sha1_compress_t compress;
sha1_update_t update;
};
#if defined(_MSC_VER)
@ -135,7 +143,7 @@ swap4b(PRUint32 value)
#define SHA_BYTESWAP(x) x = SHA_HTONL(x)
#define SHA_STORE(n) ((PRUint32*)hashout)[n] = SHA_HTONL(ctx->H[n])
#define SHA_STORE(n) ((PRUint32 *)hashout)[n] = SHA_HTONL(ctx->H[n])
#if defined(HAVE_UNALIGNED_ACCESS)
#define SHA_STORE_RESULT \
SHA_STORE(0); \

View file

@ -8,7 +8,19 @@
#define SGN_SUFFIX ".chk"
#define NSS_SIGN_CHK_MAGIC1 0xf1
#define NSS_SIGN_CHK_MAGIC2 0xc5
#define NSS_SIGN_CHK_MAJOR_VERSION 0x01
#define NSS_SIGN_CHK_MINOR_VERSION 0x02
/* new hmac based signatures */
#define NSS_SIGN_CHK_MAJOR_VERSION 0x02
#define NSS_SIGN_CHK_MINOR_VERSION 0x01
#define NSS_SIGN_CHK_TYPE_FLAGS 0xff000000
#define NSS_SIGN_CHK_FLAG_HMAC 0x80000000
typedef struct NSSSignChkHeaderStr NSSSignChkHeader;
struct NSSSignChkHeaderStr {
unsigned char magic1;
unsigned char magic2;
unsigned char majorVersion;
unsigned char minorVersion;
unsigned char offset[4];
unsigned char type[4];
};
#endif /* _SHSIGN_H_ */

View file

@ -18,6 +18,8 @@
#include "hasht.h"
#include "pqg.h"
#include "blapii.h"
#include "secitem.h"
#include "pkcs11t.h"
#ifndef NSS_FIPS_DISABLED
@ -286,10 +288,10 @@ readItem(PRFileDesc *fd, SECItem *item)
return SECSuccess;
}
static PRBool blapi_SHVerifyFile(const char *shName, PRBool self);
static PRBool blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun);
static PRBool
blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self)
blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self, PRBool rerun)
{
PRBool result = PR_FALSE; /* if anything goes wrong,
* the signature does not verify */
@ -298,7 +300,7 @@ blapi_SHVerify(const char *name, PRFuncPtr addr, PRBool self)
if (!shName) {
goto loser;
}
result = blapi_SHVerifyFile(shName, self);
result = blapi_SHVerifyFile(shName, self, rerun);
loser:
if (shName != NULL) {
@ -311,45 +313,150 @@ loser:
PRBool
BLAPI_SHVerify(const char *name, PRFuncPtr addr)
{
return blapi_SHVerify(name, addr, PR_FALSE);
PRBool rerun = PR_FALSE;
if (name && *name == BLAPI_FIPS_RERUN_FLAG) {
name++;
rerun = PR_TRUE;
}
return blapi_SHVerify(name, addr, PR_FALSE, rerun);
}
PRBool
BLAPI_SHVerifyFile(const char *shName)
{
return blapi_SHVerifyFile(shName, PR_FALSE);
PRBool rerun = PR_FALSE;
if (shName && *shName == BLAPI_FIPS_RERUN_FLAG) {
shName++;
rerun = PR_TRUE;
}
return blapi_SHVerifyFile(shName, PR_FALSE, rerun);
}
#ifndef NSS_STRICT_INTEGRITY
/* This allows checks with old shlibsign .chk files. If NSS_STRICT_INTEGRITY
* is set, we don't accept DSA */
static PRBool
blapi_SHVerifyDSACheck(PRFileDesc *shFD, const SECHashObject *hashObj,
DSAPublicKey *key, const SECItem *signature)
{
void *hashcx = NULL;
SECItem hash;
int bytesRead;
unsigned char hashBuf[HASH_LENGTH_MAX];
unsigned char buf[4096];
SECStatus rv;
hash.type = siBuffer;
hash.data = hashBuf;
hash.len = sizeof(hashBuf);
/* hash our library file */
hashcx = hashObj->create();
if (hashcx == NULL) {
return PR_FALSE;
}
hashObj->begin(hashcx);
while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
hashObj->update(hashcx, buf, bytesRead);
}
hashObj->end(hashcx, hash.data, &hash.len, hash.len);
hashObj->destroy(hashcx, PR_TRUE);
/* verify the hash against the check file */
rv = DSA_VerifyDigest(key, signature, &hash);
PORT_Memset(hashBuf, 0, sizeof hashBuf);
return (rv == SECSuccess) ? PR_TRUE : PR_FALSE;
}
#endif
#ifdef NSS_STRICT_INTEGRITY
/* don't allow MD2, MD5, SHA1 or SHA224 as your integrity hash */
static PRBool
blapi_HashAllowed(SECHashObject *hashObj)
{
switch (hashObj->type) {
case HASH_AlgSHA256:
case HASH_AlgSHA384:
case HASH_AlgSHA512:
return PR_TRUE;
default:
break;
}
return PR_FALSE;
}
#endif
static PRBool
blapi_SHVerifyHMACCheck(PRFileDesc *shFD, const SECHashObject *hashObj,
const SECItem *key, const SECItem *signature)
{
HMACContext *hmaccx = NULL;
SECItem hash;
int bytesRead;
unsigned char hashBuf[HASH_LENGTH_MAX];
unsigned char buf[4096];
SECStatus rv;
PRBool result = PR_FALSE;
#ifdef NSS_STRICT_INTEGRITY
if (!blapi_HashAllowed(hashObj)) {
return PR_FALSE;
}
#endif
hash.type = siBuffer;
hash.data = hashBuf;
hash.len = hashObj->length;
/* create an hmac for the library file */
hmaccx = HMAC_Create(hashObj, key->data, key->len, PR_TRUE);
if (hmaccx == NULL) {
return PR_FALSE;
}
HMAC_Begin(hmaccx);
while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
HMAC_Update(hmaccx, buf, bytesRead);
}
rv = HMAC_Finish(hmaccx, hash.data, &hash.len, hash.len);
HMAC_Destroy(hmaccx, PR_TRUE);
/* verify the hmac against the check file */
if (rv == SECSuccess) {
result = SECITEM_ItemsAreEqual(signature, &hash);
}
PORT_Memset(hashBuf, 0, sizeof hashBuf);
return result;
}
static PRBool
blapi_SHVerifyFile(const char *shName, PRBool self)
blapi_SHVerifyFile(const char *shName, PRBool self, PRBool rerun)
{
char *checkName = NULL;
PRFileDesc *checkFD = NULL;
PRFileDesc *shFD = NULL;
void *hashcx = NULL;
const SECHashObject *hashObj = NULL;
SECItem signature = { 0, NULL, 0 };
SECItem hash;
int bytesRead, offset;
int bytesRead, offset, type;
SECStatus rv;
DSAPublicKey key;
int count;
SECItem hmacKey = { 0, NULL, 0 };
#ifdef FREEBL_USE_PRELINK
int pid = 0;
#endif
PRBool result = PR_FALSE; /* if anything goes wrong,
* the signature does not verify */
unsigned char buf[4096];
unsigned char hashBuf[HASH_LENGTH_MAX];
* the signature does not verify */
NSSSignChkHeader header;
#ifndef NSS_STRICT_INTEGRITY
DSAPublicKey key;
PORT_Memset(&key, 0, sizeof(key));
hash.data = hashBuf;
hash.len = sizeof(hashBuf);
#endif
/* If our integrity check was never ran or failed, fail any other
* integrity checks to prevent any token going into FIPS mode. */
if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) {
if (!self && (BL_FIPSEntryOK(PR_FALSE, rerun) != SECSuccess)) {
return PR_FALSE;
}
@ -374,57 +481,82 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
}
/* read and Verify the headerthe header */
bytesRead = PR_Read(checkFD, buf, 12);
if (bytesRead != 12) {
bytesRead = PR_Read(checkFD, &header, sizeof(header));
if (bytesRead != sizeof(header)) {
goto loser;
}
if ((buf[0] != NSS_SIGN_CHK_MAGIC1) || (buf[1] != NSS_SIGN_CHK_MAGIC2)) {
if ((header.magic1 != NSS_SIGN_CHK_MAGIC1) ||
(header.magic2 != NSS_SIGN_CHK_MAGIC2)) {
goto loser;
}
if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) ||
(buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) {
/* we've bumped the version number so that newly signed .check
* files will fail nicely on old version of nss */
if (header.majorVersion > NSS_SIGN_CHK_MAJOR_VERSION) {
goto loser;
}
#ifdef notdef
if (decodeInt(&buf[8]) != CKK_DSA) {
if (header.minorVersion < NSS_SIGN_CHK_MINOR_VERSION) {
goto loser;
}
#endif
type = decodeInt(header.type);
/* seek past any future header extensions */
offset = decodeInt(&buf[4]);
offset = decodeInt(header.offset);
if (PR_Seek(checkFD, offset, PR_SEEK_SET) < 0) {
goto loser;
}
/* read the key */
rv = readItem(checkFD, &key.params.prime);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.params.subPrime);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.params.base);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.publicValue);
if (rv != SECSuccess) {
goto loser;
}
/* read the siganture */
rv = readItem(checkFD, &signature);
if (rv != SECSuccess) {
goto loser;
switch (type) {
case CKK_DSA:
#ifdef NSS_STRICT_INTEGRITY
goto loser;
#else
/* accept old dsa check files if NSS_STRICT_INTEGRITY is not set*/
/* read the key */
rv = readItem(checkFD, &key.params.prime);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.params.subPrime);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.params.base);
if (rv != SECSuccess) {
goto loser;
}
rv = readItem(checkFD, &key.publicValue);
if (rv != SECSuccess) {
goto loser;
}
/* read the signature */
rv = readItem(checkFD, &signature);
if (rv != SECSuccess) {
goto loser;
}
hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
break;
#endif
default:
if ((type & NSS_SIGN_CHK_TYPE_FLAGS) != NSS_SIGN_CHK_FLAG_HMAC) {
goto loser;
}
/* read the HMAC Key */
rv = readItem(checkFD, &hmacKey);
if (rv != SECSuccess) {
goto loser;
}
/* read the siganture */
rv = readItem(checkFD, &signature);
if (rv != SECSuccess) {
goto loser;
}
hashObj = HASH_GetRawHashObject(type & ~NSS_SIGN_CHK_TYPE_FLAGS);
}
/* done with the check file */
PR_Close(checkFD);
checkFD = NULL;
hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
if (hashObj == NULL) {
goto loser;
}
@ -443,18 +575,20 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
goto loser;
}
/* hash our library file with SHA1 */
hashcx = hashObj->create();
if (hashcx == NULL) {
goto loser;
switch (type) {
case CKK_DSA:
#ifndef NSS_STRICT_INTEGRITY
result = blapi_SHVerifyDSACheck(shFD, hashObj, &key, &signature);
#endif
break;
default:
if ((type & NSS_SIGN_CHK_TYPE_FLAGS) != NSS_SIGN_CHK_FLAG_HMAC) {
break;
}
result = blapi_SHVerifyHMACCheck(shFD, hashObj, &hmacKey, &signature);
break;
}
hashObj->begin(hashcx);
count = 0;
while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
hashObj->update(hashcx, buf, bytesRead);
count += bytesRead;
}
#ifdef FREEBL_USE_PRELINK
bl_CloseUnPrelink(shFD, pid);
#else
@ -462,38 +596,8 @@ blapi_SHVerifyFile(const char *shName, PRBool self)
#endif
shFD = NULL;
hashObj->end(hashcx, hash.data, &hash.len, hash.len);
/* verify the hash against the check file */
if (DSA_VerifyDigest(&key, &signature, &hash) == SECSuccess) {
result = PR_TRUE;
}
#ifdef DEBUG_SHVERIFY
{
int i, j;
fprintf(stderr, "File %s: %d bytes\n", shName, count);
fprintf(stderr, " hash: %d bytes\n", hash.len);
#define STEP 10
for (i = 0; i < hash.len; i += STEP) {
fprintf(stderr, " ");
for (j = 0; j < STEP && (i + j) < hash.len; j++) {
fprintf(stderr, " %02x", hash.data[i + j]);
}
fprintf(stderr, "\n");
}
fprintf(stderr, " signature: %d bytes\n", signature.len);
for (i = 0; i < signature.len; i += STEP) {
fprintf(stderr, " ");
for (j = 0; j < STEP && (i + j) < signature.len; j++) {
fprintf(stderr, " %02x", signature.data[i + j]);
}
fprintf(stderr, "\n");
}
fprintf(stderr, "Verified : %s\n", result ? "TRUE" : "FALSE");
}
#endif /* DEBUG_SHVERIFY */
loser:
PORT_Memset(&header, 0, sizeof header);
if (checkName != NULL) {
PORT_Free(checkName);
}
@ -503,27 +607,26 @@ loser:
if (shFD != NULL) {
PR_Close(shFD);
}
if (hashcx != NULL) {
if (hashObj) {
hashObj->destroy(hashcx, PR_TRUE);
}
if (hmacKey.data != NULL) {
SECITEM_ZfreeItem(&hmacKey, PR_FALSE);
}
if (signature.data != NULL) {
PORT_Free(signature.data);
SECITEM_ZfreeItem(&signature, PR_FALSE);
}
#ifndef NSS_STRICT_INTEGRITY
if (key.params.prime.data != NULL) {
PORT_Free(key.params.prime.data);
SECITEM_ZfreeItem(&key.params.prime, PR_FALSE);
}
if (key.params.subPrime.data != NULL) {
PORT_Free(key.params.subPrime.data);
SECITEM_ZfreeItem(&key.params.subPrime, PR_FALSE);
}
if (key.params.base.data != NULL) {
PORT_Free(key.params.base.data);
SECITEM_ZfreeItem(&key.params.base, PR_FALSE);
}
if (key.publicValue.data != NULL) {
PORT_Free(key.publicValue.data);
SECITEM_ZfreeItem(&key.publicValue, PR_FALSE);
}
#endif
return result;
}
@ -532,12 +635,12 @@ BLAPI_VerifySelf(const char *name)
{
if (name == NULL) {
/*
* If name is NULL, freebl is statically linked into softoken.
* softoken will call BLAPI_SHVerify next to verify itself.
*/
* If name is NULL, freebl is statically linked into softoken.
* softoken will call BLAPI_SHVerify next to verify itself.
*/
return PR_TRUE;
}
return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE);
return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE, PR_FALSE);
}
#else /* NSS_FIPS_DISABLED */

View file

@ -86,6 +86,10 @@
if (ptr_##fn) { \
return ptr_##fn(a1, a2, a3, a4); \
}
#define STUB_SAFE_CALL5(fn, a1, a2, a3, a4, a5) \
if (ptr_##fn) { \
return ptr_##fn(a1, a2, a3, a4, a5); \
}
#define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
if (ptr_##fn) { \
return ptr_##fn(a1, a2, a3, a4, a5, a6); \
@ -142,11 +146,8 @@ STUB_DECLARE(int, PORT_GetError_Util, (void));
STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
STUB_DECLARE(void, PORT_SetError_Util, (int value));
STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment,
void **mem));
STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes,
size_t alignment,
size_t offset));
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment, void **mem));
STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes, size_t alignment, size_t offset));
STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
@ -156,36 +157,31 @@ STUB_DECLARE(PRStatus, PR_Close, (PRFileDesc * fd));
STUB_DECLARE(void, PR_DestroyLock, (PRLock * lock));
STUB_DECLARE(void, PR_DestroyCondVar, (PRCondVar * cvar));
STUB_DECLARE(void, PR_Free, (void *ptr));
STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name,
PRFuncPtr addr));
STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name, PRFuncPtr addr));
STUB_DECLARE(PRFileDesc *, PR_ImportPipe, (PROsfd osfd));
STUB_DECLARE(void, PR_Lock, (PRLock * lock));
STUB_DECLARE(PRCondVar *, PR_NewCondVar, (PRLock * lock));
STUB_DECLARE(PRLock *, PR_NewLock, (void));
STUB_DECLARE(PRStatus, PR_NotifyCondVar, (PRCondVar * cvar));
STUB_DECLARE(PRStatus, PR_NotifyAllCondVar, (PRCondVar * cvar));
STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags,
PRIntn mode));
STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags, PRIntn mode));
STUB_DECLARE(PRInt32, PR_Read, (PRFileDesc * fd, void *buf, PRInt32 amount));
STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset,
PRSeekWhence whence));
STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset, PRSeekWhence whence));
STUB_DECLARE(PRStatus, PR_Sleep, (PRIntervalTime ticks));
STUB_DECLARE(PRStatus, PR_Unlock, (PRLock * lock));
STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar,
PRIntervalTime timeout));
STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar, PRIntervalTime timeout));
STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena,
SECItem *item, unsigned int len));
STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a,
const SECItem *b));
STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena,
SECItem *to, const SECItem *from));
STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena, SECItem *item, unsigned int len));
STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a, const SECItem *b));
STUB_DECLARE(PRBool, SECITEM_ItemsAreEqual_Util, (const SECItem *a, const SECItem *b));
STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena, SECItem *to, const SECItem *from));
STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
STUB_DECLARE(unsigned int, NSS_SecureMemcmpZero, (const void *mem, size_t n));
STUB_DECLARE(void, NSS_SecureSelect, (void *dest, const void *src0, const void *src1, size_t n, unsigned char b));
#define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
#define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
@ -294,6 +290,13 @@ PR_Free_stub(void *ptr)
return free(ptr);
}
/* we have defensive returns after abort(), which is marked noreturn on some
* platforms, making the compiler legitimately complain. */
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code-return"
#endif
/*
* arenas
*
@ -576,8 +579,11 @@ extern char *
PR_GetEnvSecure_stub(const char *var)
{
STUB_SAFE_CALL1(PR_GetEnvSecure, var);
abort();
return NULL;
#ifdef __USE_GNU
return secure_getenv(var);
#else
return getenv(var);
#endif
}
extern void
@ -625,6 +631,30 @@ SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
return SECEqual;
}
extern PRBool
SECITEM_ItemsAreEqual_stub(const SECItem *a, const SECItem *b)
{
STUB_SAFE_CALL2(SECITEM_ItemsAreEqual_Util, a, b);
/* two nulls are equal */
if (!a && !b) {
return PR_TRUE;
}
/* only one NULL is not equal */
if (!a || !b) {
return PR_FALSE;
}
/* we know both secitems have been set, now make sure the lengths
* are equal */
if (a->len != b->len) {
return PR_FALSE;
}
/* lengths are equal, safe to verify the data */
if (PORT_Memcmp(a->data, b->data, b->len) != 0) {
return PR_FALSE;
}
return PR_TRUE;
}
extern SECStatus
SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
{
@ -641,11 +671,24 @@ SECOID_FindOIDTag_stub(const SECItem *oid)
return SEC_OID_UNKNOWN;
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
extern void
SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
{
STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
abort();
if (zap) {
if (zap->data) {
PORT_Memset(zap->data, 0, zap->len);
PORT_Free_stub(zap->data);
}
PORT_Memset(zap, 0, sizeof(SECItem));
if (freeit) {
PORT_Free_stub(zap);
}
}
}
extern int
@ -662,6 +705,13 @@ NSS_SecureMemcmpZero_stub(const void *mem, size_t n)
abort();
}
extern void
NSS_SecureSelect_stub(void *dest, const void *src0, const void *src1, size_t n, unsigned char b)
{
STUB_SAFE_CALL5(NSS_SecureSelect, dest, src0, src1, n, b);
abort();
}
#ifdef FREEBL_NO_WEAK
static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
@ -715,6 +765,7 @@ freebl_InitNSSUtil(void *lib)
STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
STUB_FETCH_FUNCTION(NSS_SecureMemcmpZero);
STUB_FETCH_FUNCTION(NSS_SecureSelect);
return SECSuccess;
}

View file

@ -35,12 +35,14 @@
#define SECITEM_AllocItem SECITEM_AllocItem_stub
#define SECITEM_CompareItem SECITEM_CompareItem_stub
#define SECITEM_ItemsAreEqual SECITEM_ItemsAreEqual_stub
#define SECITEM_CopyItem SECITEM_CopyItem_stub
#define SECITEM_FreeItem SECITEM_FreeItem_stub
#define SECITEM_ZfreeItem SECITEM_ZfreeItem_stub
#define SECOID_FindOIDTag SECOID_FindOIDTag_stub
#define NSS_SecureMemcmp NSS_SecureMemcmp_stub
#define NSS_SecureMemcmpZero NSS_SecureMemcmpZero_stub
#define NSS_SecureSelect NSS_SecureSelect_stub
#define PR_Assert PR_Assert_stub
#define PR_Access PR_Access_stub

View file

@ -8,9 +8,9 @@
#include "seccomon.h"
#if (defined(XP_UNIX) || defined(XP_BEOS)) && defined(SEED_ONLY_DEV_URANDOM)
#if defined(XP_UNIX) && defined(SEED_ONLY_DEV_URANDOM)
#include "unix_urandom.c"
#elif defined(XP_UNIX) || defined(XP_BEOS)
#elif defined(XP_UNIX)
#include "unix_rand.c"
#endif
#ifdef XP_WIN

View file

@ -287,49 +287,6 @@ GiveSystemInfo(void)
}
#endif /* HPUX */
#if defined(OSF1)
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/systeminfo.h>
#include <c_asm.h>
static void
GiveSystemInfo(void)
{
char buf[BUFSIZ];
int rv;
int off = 0;
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
if (rv > 0) {
RNG_RandomUpdate(buf, rv);
}
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
if (rv > 0) {
RNG_RandomUpdate(buf, rv);
}
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
if (rv > 0) {
RNG_RandomUpdate(buf, rv);
}
}
/*
* Use the "get the cycle counter" instruction on the alpha.
* The low 32 bits completely turn over in less than a minute.
* The high 32 bits are some non-counter gunk that changes sometimes.
*/
static size_t
GetHighResClock(void *buf, size_t maxbytes)
{
unsigned long t;
t = asm("rpcc %v0");
return CopyLowBits(buf, maxbytes, &t, sizeof(t));
}
#endif /* Alpha */
#if defined(_IBMR2)
static size_t
GetHighResClock(void *buf, size_t maxbytes)
@ -586,39 +543,6 @@ GiveSystemInfo(void)
}
#endif /* sinix */
#ifdef BEOS
#include <be/kernel/OS.h>
static size_t
GetHighResClock(void *buf, size_t maxbytes)
{
bigtime_t bigtime; /* Actually a int64 */
bigtime = real_time_clock_usecs();
return CopyLowBits(buf, maxbytes, &bigtime, sizeof(bigtime));
}
static void
GiveSystemInfo(void)
{
system_info *info = NULL;
PRInt32 val;
get_system_info(info);
if (info) {
val = info->boot_time;
RNG_RandomUpdate(&val, sizeof(val));
val = info->used_pages;
RNG_RandomUpdate(&val, sizeof(val));
val = info->used_ports;
RNG_RandomUpdate(&val, sizeof(val));
val = info->used_threads;
RNG_RandomUpdate(&val, sizeof(val));
val = info->used_teams;
RNG_RandomUpdate(&val, sizeof(val));
}
}
#endif /* BEOS */
#if defined(nec_ews)
#include <sys/systeminfo.h>
@ -692,16 +616,6 @@ RNG_SystemInfoForRNG(void)
#else
extern char **environ;
#endif
#ifdef BEOS
static const char *const files[] = {
"/boot/var/swap",
"/boot/var/log/syslog",
"/boot/var/tmp",
"/boot/home/config/settings",
"/boot/home",
0
};
#else
static const char *const files[] = {
"/etc/passwd",
"/etc/utmp",
@ -710,7 +624,6 @@ RNG_SystemInfoForRNG(void)
"/usr/tmp",
0
};
#endif
GiveSystemInfo();

View file

@ -22,6 +22,7 @@ RNG_SystemInfoForRNG(void)
return;
}
RNG_RandomUpdate(bytes, numBytes);
PORT_Memset(bytes, 0, sizeof bytes);
}
size_t

View file

@ -1,255 +0,0 @@
/* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file was auto-generated by KreMLin! */
#include "FStar.h"
static uint64_t
FStar_UInt128_constant_time_carry(uint64_t a, uint64_t b)
{
return (a ^ ((a ^ b) | ((a - b) ^ b))) >> (uint32_t)63U;
}
static uint64_t
FStar_UInt128_carry(uint64_t a, uint64_t b)
{
return FStar_UInt128_constant_time_carry(a, b);
}
FStar_UInt128_uint128
FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low + b.low,
.high = a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low + b.low,
.high = a.high + b.high + FStar_UInt128_carry(a.low + b.low, b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low - b.low,
.high = a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) });
}
static FStar_UInt128_uint128
FStar_UInt128_sub_mod_impl(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = a.low - b.low,
.high = a.high - b.high - FStar_UInt128_carry(a.low, a.low - b.low) });
}
FStar_UInt128_uint128
FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return FStar_UInt128_sub_mod_impl(a, b);
}
FStar_UInt128_uint128
FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low & b.low, .high = a.high & b.high });
}
FStar_UInt128_uint128
FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low ^ b.low, .high = a.high ^ b.high });
}
FStar_UInt128_uint128
FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return ((FStar_UInt128_uint128){.low = a.low | b.low, .high = a.high | b.high });
}
FStar_UInt128_uint128
FStar_UInt128_lognot(FStar_UInt128_uint128 a)
{
return ((FStar_UInt128_uint128){.low = ~a.low, .high = ~a.high });
}
static uint32_t FStar_UInt128_u32_64 = (uint32_t)64U;
static uint64_t
FStar_UInt128_add_u64_shift_left(uint64_t hi, uint64_t lo, uint32_t s)
{
return (hi << s) + (lo >> (FStar_UInt128_u32_64 - s));
}
static uint64_t
FStar_UInt128_add_u64_shift_left_respec(uint64_t hi, uint64_t lo, uint32_t s)
{
return FStar_UInt128_add_u64_shift_left(hi, lo, s);
}
static FStar_UInt128_uint128
FStar_UInt128_shift_left_small(FStar_UInt128_uint128 a, uint32_t s)
{
if (s == (uint32_t)0U)
return a;
else
return (
(FStar_UInt128_uint128){
.low = a.low << s,
.high = FStar_UInt128_add_u64_shift_left_respec(a.high, a.low, s) });
}
static FStar_UInt128_uint128
FStar_UInt128_shift_left_large(FStar_UInt128_uint128 a, uint32_t s)
{
return ((FStar_UInt128_uint128){.low = (uint64_t)0U, .high = a.low << (s - FStar_UInt128_u32_64) });
}
FStar_UInt128_uint128
FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s)
{
if (s < FStar_UInt128_u32_64)
return FStar_UInt128_shift_left_small(a, s);
else
return FStar_UInt128_shift_left_large(a, s);
}
static uint64_t
FStar_UInt128_add_u64_shift_right(uint64_t hi, uint64_t lo, uint32_t s)
{
return (lo >> s) + (hi << (FStar_UInt128_u32_64 - s));
}
static uint64_t
FStar_UInt128_add_u64_shift_right_respec(uint64_t hi, uint64_t lo, uint32_t s)
{
return FStar_UInt128_add_u64_shift_right(hi, lo, s);
}
static FStar_UInt128_uint128
FStar_UInt128_shift_right_small(FStar_UInt128_uint128 a, uint32_t s)
{
if (s == (uint32_t)0U)
return a;
else
return (
(FStar_UInt128_uint128){
.low = FStar_UInt128_add_u64_shift_right_respec(a.high, a.low, s),
.high = a.high >> s });
}
static FStar_UInt128_uint128
FStar_UInt128_shift_right_large(FStar_UInt128_uint128 a, uint32_t s)
{
return ((FStar_UInt128_uint128){.low = a.high >> (s - FStar_UInt128_u32_64), .high = (uint64_t)0U });
}
FStar_UInt128_uint128
FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s)
{
if (s < FStar_UInt128_u32_64)
return FStar_UInt128_shift_right_small(a, s);
else
return FStar_UInt128_shift_right_large(a, s);
}
FStar_UInt128_uint128
FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = FStar_UInt64_eq_mask(a.low, b.low) & FStar_UInt64_eq_mask(a.high, b.high),
.high = FStar_UInt64_eq_mask(a.low, b.low) & FStar_UInt64_eq_mask(a.high, b.high) });
}
FStar_UInt128_uint128
FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
return (
(FStar_UInt128_uint128){
.low = (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)),
.high = (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low)) });
}
FStar_UInt128_uint128
FStar_UInt128_uint64_to_uint128(uint64_t a)
{
return ((FStar_UInt128_uint128){.low = a, .high = (uint64_t)0U });
}
uint64_t
FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a)
{
return a.low;
}
static uint64_t FStar_UInt128_u64_l32_mask = (uint64_t)0xffffffffU;
static uint64_t
FStar_UInt128_u64_mod_32(uint64_t a)
{
return a & FStar_UInt128_u64_l32_mask;
}
static uint32_t FStar_UInt128_u32_32 = (uint32_t)32U;
static K___uint64_t_uint64_t_uint64_t_uint64_t
FStar_UInt128_mul_wide_impl_t_(uint64_t x, uint64_t y)
{
return (
(K___uint64_t_uint64_t_uint64_t_uint64_t){
.fst = FStar_UInt128_u64_mod_32(x),
.snd = FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y)),
.thd = x >> FStar_UInt128_u32_32,
.f3 = (x >> FStar_UInt128_u32_32) * FStar_UInt128_u64_mod_32(y) + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32) });
}
static uint64_t
FStar_UInt128_u32_combine_(uint64_t hi, uint64_t lo)
{
return lo + (hi << FStar_UInt128_u32_32);
}
static FStar_UInt128_uint128
FStar_UInt128_mul_wide_impl(uint64_t x, uint64_t y)
{
K___uint64_t_uint64_t_uint64_t_uint64_t scrut = FStar_UInt128_mul_wide_impl_t_(x, y);
uint64_t u1 = scrut.fst;
uint64_t w3 = scrut.snd;
uint64_t x_ = scrut.thd;
uint64_t t_ = scrut.f3;
return (
(FStar_UInt128_uint128){
.low = FStar_UInt128_u32_combine_(u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_),
w3),
.high = x_ * (y >> FStar_UInt128_u32_32) + (t_ >> FStar_UInt128_u32_32) +
((u1 * (y >> FStar_UInt128_u32_32) + FStar_UInt128_u64_mod_32(t_)) >> FStar_UInt128_u32_32) });
}
FStar_UInt128_uint128
FStar_UInt128_mul_wide(uint64_t x, uint64_t y)
{
return FStar_UInt128_mul_wide_impl(x, y);
}

View file

@ -1,69 +0,0 @@
/* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* This file was auto-generated by KreMLin! */
#ifndef __FStar_H
#define __FStar_H
#include "kremlib_base.h"
typedef struct
{
uint64_t low;
uint64_t high;
} FStar_UInt128_uint128;
typedef FStar_UInt128_uint128 FStar_UInt128_t;
extern void FStar_UInt128_constant_time_carry_ok(uint64_t x0, uint64_t x1);
FStar_UInt128_uint128 FStar_UInt128_add(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_add_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_sub(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_sub_mod(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logand(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logxor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_logor(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_lognot(FStar_UInt128_uint128 a);
FStar_UInt128_uint128 FStar_UInt128_shift_left(FStar_UInt128_uint128 a, uint32_t s);
FStar_UInt128_uint128 FStar_UInt128_shift_right(FStar_UInt128_uint128 a, uint32_t s);
FStar_UInt128_uint128 FStar_UInt128_eq_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b);
FStar_UInt128_uint128 FStar_UInt128_uint64_to_uint128(uint64_t a);
uint64_t FStar_UInt128_uint128_to_uint64(FStar_UInt128_uint128 a);
typedef struct
{
uint64_t fst;
uint64_t snd;
uint64_t thd;
uint64_t f3;
} K___uint64_t_uint64_t_uint64_t_uint64_t;
FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t y);
#endif

View file

@ -0,0 +1,678 @@
/* MIT License
*
* Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation
*
* 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.
*/
#ifndef __Hacl_Bignum25519_51_H
#define __Hacl_Bignum25519_51_H
#if defined(__cplusplus)
extern "C" {
#endif
#include <string.h>
#include "krml/internal/types.h"
#include "krml/lowstar_endianness.h"
#include "krml/internal/target.h"
#include "Hacl_Krmllib.h"
static inline void
Hacl_Impl_Curve25519_Field51_fadd(uint64_t *out, uint64_t *f1, uint64_t *f2)
{
uint64_t f10 = f1[0U];
uint64_t f20 = f2[0U];
uint64_t f11 = f1[1U];
uint64_t f21 = f2[1U];
uint64_t f12 = f1[2U];
uint64_t f22 = f2[2U];
uint64_t f13 = f1[3U];
uint64_t f23 = f2[3U];
uint64_t f14 = f1[4U];
uint64_t f24 = f2[4U];
out[0U] = f10 + f20;
out[1U] = f11 + f21;
out[2U] = f12 + f22;
out[3U] = f13 + f23;
out[4U] = f14 + f24;
}
static inline void
Hacl_Impl_Curve25519_Field51_fsub(uint64_t *out, uint64_t *f1, uint64_t *f2)
{
uint64_t f10 = f1[0U];
uint64_t f20 = f2[0U];
uint64_t f11 = f1[1U];
uint64_t f21 = f2[1U];
uint64_t f12 = f1[2U];
uint64_t f22 = f2[2U];
uint64_t f13 = f1[3U];
uint64_t f23 = f2[3U];
uint64_t f14 = f1[4U];
uint64_t f24 = f2[4U];
out[0U] = f10 + (uint64_t)0x3fffffffffff68U - f20;
out[1U] = f11 + (uint64_t)0x3ffffffffffff8U - f21;
out[2U] = f12 + (uint64_t)0x3ffffffffffff8U - f22;
out[3U] = f13 + (uint64_t)0x3ffffffffffff8U - f23;
out[4U] = f14 + (uint64_t)0x3ffffffffffff8U - f24;
}
static inline void
Hacl_Impl_Curve25519_Field51_fmul(
uint64_t *out,
uint64_t *f1,
uint64_t *f2,
FStar_UInt128_uint128 *uu___)
{
uint64_t f10 = f1[0U];
uint64_t f11 = f1[1U];
uint64_t f12 = f1[2U];
uint64_t f13 = f1[3U];
uint64_t f14 = f1[4U];
uint64_t f20 = f2[0U];
uint64_t f21 = f2[1U];
uint64_t f22 = f2[2U];
uint64_t f23 = f2[3U];
uint64_t f24 = f2[4U];
uint64_t tmp1 = f21 * (uint64_t)19U;
uint64_t tmp2 = f22 * (uint64_t)19U;
uint64_t tmp3 = f23 * (uint64_t)19U;
uint64_t tmp4 = f24 * (uint64_t)19U;
FStar_UInt128_uint128 o00 = FStar_UInt128_mul_wide(f10, f20);
FStar_UInt128_uint128 o10 = FStar_UInt128_mul_wide(f10, f21);
FStar_UInt128_uint128 o20 = FStar_UInt128_mul_wide(f10, f22);
FStar_UInt128_uint128 o30 = FStar_UInt128_mul_wide(f10, f23);
FStar_UInt128_uint128 o40 = FStar_UInt128_mul_wide(f10, f24);
FStar_UInt128_uint128 o01 = FStar_UInt128_add(o00, FStar_UInt128_mul_wide(f11, tmp4));
FStar_UInt128_uint128 o11 = FStar_UInt128_add(o10, FStar_UInt128_mul_wide(f11, f20));
FStar_UInt128_uint128 o21 = FStar_UInt128_add(o20, FStar_UInt128_mul_wide(f11, f21));
FStar_UInt128_uint128 o31 = FStar_UInt128_add(o30, FStar_UInt128_mul_wide(f11, f22));
FStar_UInt128_uint128 o41 = FStar_UInt128_add(o40, FStar_UInt128_mul_wide(f11, f23));
FStar_UInt128_uint128 o02 = FStar_UInt128_add(o01, FStar_UInt128_mul_wide(f12, tmp3));
FStar_UInt128_uint128 o12 = FStar_UInt128_add(o11, FStar_UInt128_mul_wide(f12, tmp4));
FStar_UInt128_uint128 o22 = FStar_UInt128_add(o21, FStar_UInt128_mul_wide(f12, f20));
FStar_UInt128_uint128 o32 = FStar_UInt128_add(o31, FStar_UInt128_mul_wide(f12, f21));
FStar_UInt128_uint128 o42 = FStar_UInt128_add(o41, FStar_UInt128_mul_wide(f12, f22));
FStar_UInt128_uint128 o03 = FStar_UInt128_add(o02, FStar_UInt128_mul_wide(f13, tmp2));
FStar_UInt128_uint128 o13 = FStar_UInt128_add(o12, FStar_UInt128_mul_wide(f13, tmp3));
FStar_UInt128_uint128 o23 = FStar_UInt128_add(o22, FStar_UInt128_mul_wide(f13, tmp4));
FStar_UInt128_uint128 o33 = FStar_UInt128_add(o32, FStar_UInt128_mul_wide(f13, f20));
FStar_UInt128_uint128 o43 = FStar_UInt128_add(o42, FStar_UInt128_mul_wide(f13, f21));
FStar_UInt128_uint128 o04 = FStar_UInt128_add(o03, FStar_UInt128_mul_wide(f14, tmp1));
FStar_UInt128_uint128 o14 = FStar_UInt128_add(o13, FStar_UInt128_mul_wide(f14, tmp2));
FStar_UInt128_uint128 o24 = FStar_UInt128_add(o23, FStar_UInt128_mul_wide(f14, tmp3));
FStar_UInt128_uint128 o34 = FStar_UInt128_add(o33, FStar_UInt128_mul_wide(f14, tmp4));
FStar_UInt128_uint128 o44 = FStar_UInt128_add(o43, FStar_UInt128_mul_wide(f14, f20));
FStar_UInt128_uint128 tmp_w0 = o04;
FStar_UInt128_uint128 tmp_w1 = o14;
FStar_UInt128_uint128 tmp_w2 = o24;
FStar_UInt128_uint128 tmp_w3 = o34;
FStar_UInt128_uint128 tmp_w4 = o44;
FStar_UInt128_uint128
l_ = FStar_UInt128_add(tmp_w0, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp01 = FStar_UInt128_uint128_to_uint64(l_) & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_, (uint32_t)51U));
FStar_UInt128_uint128 l_0 = FStar_UInt128_add(tmp_w1, FStar_UInt128_uint64_to_uint128(c0));
uint64_t tmp11 = FStar_UInt128_uint128_to_uint64(l_0) & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_0, (uint32_t)51U));
FStar_UInt128_uint128 l_1 = FStar_UInt128_add(tmp_w2, FStar_UInt128_uint64_to_uint128(c1));
uint64_t tmp21 = FStar_UInt128_uint128_to_uint64(l_1) & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_1, (uint32_t)51U));
FStar_UInt128_uint128 l_2 = FStar_UInt128_add(tmp_w3, FStar_UInt128_uint64_to_uint128(c2));
uint64_t tmp31 = FStar_UInt128_uint128_to_uint64(l_2) & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_2, (uint32_t)51U));
FStar_UInt128_uint128 l_3 = FStar_UInt128_add(tmp_w4, FStar_UInt128_uint64_to_uint128(c3));
uint64_t tmp41 = FStar_UInt128_uint128_to_uint64(l_3) & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_3, (uint32_t)51U));
uint64_t l_4 = tmp01 + c4 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_4 >> (uint32_t)51U;
uint64_t o0 = tmp0_;
uint64_t o1 = tmp11 + c5;
uint64_t o2 = tmp21;
uint64_t o3 = tmp31;
uint64_t o4 = tmp41;
out[0U] = o0;
out[1U] = o1;
out[2U] = o2;
out[3U] = o3;
out[4U] = o4;
}
static inline void
Hacl_Impl_Curve25519_Field51_fmul2(
uint64_t *out,
uint64_t *f1,
uint64_t *f2,
FStar_UInt128_uint128 *uu___)
{
uint64_t f10 = f1[0U];
uint64_t f11 = f1[1U];
uint64_t f12 = f1[2U];
uint64_t f13 = f1[3U];
uint64_t f14 = f1[4U];
uint64_t f20 = f2[0U];
uint64_t f21 = f2[1U];
uint64_t f22 = f2[2U];
uint64_t f23 = f2[3U];
uint64_t f24 = f2[4U];
uint64_t f30 = f1[5U];
uint64_t f31 = f1[6U];
uint64_t f32 = f1[7U];
uint64_t f33 = f1[8U];
uint64_t f34 = f1[9U];
uint64_t f40 = f2[5U];
uint64_t f41 = f2[6U];
uint64_t f42 = f2[7U];
uint64_t f43 = f2[8U];
uint64_t f44 = f2[9U];
uint64_t tmp11 = f21 * (uint64_t)19U;
uint64_t tmp12 = f22 * (uint64_t)19U;
uint64_t tmp13 = f23 * (uint64_t)19U;
uint64_t tmp14 = f24 * (uint64_t)19U;
uint64_t tmp21 = f41 * (uint64_t)19U;
uint64_t tmp22 = f42 * (uint64_t)19U;
uint64_t tmp23 = f43 * (uint64_t)19U;
uint64_t tmp24 = f44 * (uint64_t)19U;
FStar_UInt128_uint128 o00 = FStar_UInt128_mul_wide(f10, f20);
FStar_UInt128_uint128 o15 = FStar_UInt128_mul_wide(f10, f21);
FStar_UInt128_uint128 o25 = FStar_UInt128_mul_wide(f10, f22);
FStar_UInt128_uint128 o30 = FStar_UInt128_mul_wide(f10, f23);
FStar_UInt128_uint128 o40 = FStar_UInt128_mul_wide(f10, f24);
FStar_UInt128_uint128 o010 = FStar_UInt128_add(o00, FStar_UInt128_mul_wide(f11, tmp14));
FStar_UInt128_uint128 o110 = FStar_UInt128_add(o15, FStar_UInt128_mul_wide(f11, f20));
FStar_UInt128_uint128 o210 = FStar_UInt128_add(o25, FStar_UInt128_mul_wide(f11, f21));
FStar_UInt128_uint128 o310 = FStar_UInt128_add(o30, FStar_UInt128_mul_wide(f11, f22));
FStar_UInt128_uint128 o410 = FStar_UInt128_add(o40, FStar_UInt128_mul_wide(f11, f23));
FStar_UInt128_uint128 o020 = FStar_UInt128_add(o010, FStar_UInt128_mul_wide(f12, tmp13));
FStar_UInt128_uint128 o120 = FStar_UInt128_add(o110, FStar_UInt128_mul_wide(f12, tmp14));
FStar_UInt128_uint128 o220 = FStar_UInt128_add(o210, FStar_UInt128_mul_wide(f12, f20));
FStar_UInt128_uint128 o320 = FStar_UInt128_add(o310, FStar_UInt128_mul_wide(f12, f21));
FStar_UInt128_uint128 o420 = FStar_UInt128_add(o410, FStar_UInt128_mul_wide(f12, f22));
FStar_UInt128_uint128 o030 = FStar_UInt128_add(o020, FStar_UInt128_mul_wide(f13, tmp12));
FStar_UInt128_uint128 o130 = FStar_UInt128_add(o120, FStar_UInt128_mul_wide(f13, tmp13));
FStar_UInt128_uint128 o230 = FStar_UInt128_add(o220, FStar_UInt128_mul_wide(f13, tmp14));
FStar_UInt128_uint128 o330 = FStar_UInt128_add(o320, FStar_UInt128_mul_wide(f13, f20));
FStar_UInt128_uint128 o430 = FStar_UInt128_add(o420, FStar_UInt128_mul_wide(f13, f21));
FStar_UInt128_uint128 o040 = FStar_UInt128_add(o030, FStar_UInt128_mul_wide(f14, tmp11));
FStar_UInt128_uint128 o140 = FStar_UInt128_add(o130, FStar_UInt128_mul_wide(f14, tmp12));
FStar_UInt128_uint128 o240 = FStar_UInt128_add(o230, FStar_UInt128_mul_wide(f14, tmp13));
FStar_UInt128_uint128 o340 = FStar_UInt128_add(o330, FStar_UInt128_mul_wide(f14, tmp14));
FStar_UInt128_uint128 o440 = FStar_UInt128_add(o430, FStar_UInt128_mul_wide(f14, f20));
FStar_UInt128_uint128 tmp_w10 = o040;
FStar_UInt128_uint128 tmp_w11 = o140;
FStar_UInt128_uint128 tmp_w12 = o240;
FStar_UInt128_uint128 tmp_w13 = o340;
FStar_UInt128_uint128 tmp_w14 = o440;
FStar_UInt128_uint128 o0 = FStar_UInt128_mul_wide(f30, f40);
FStar_UInt128_uint128 o1 = FStar_UInt128_mul_wide(f30, f41);
FStar_UInt128_uint128 o2 = FStar_UInt128_mul_wide(f30, f42);
FStar_UInt128_uint128 o3 = FStar_UInt128_mul_wide(f30, f43);
FStar_UInt128_uint128 o4 = FStar_UInt128_mul_wide(f30, f44);
FStar_UInt128_uint128 o01 = FStar_UInt128_add(o0, FStar_UInt128_mul_wide(f31, tmp24));
FStar_UInt128_uint128 o111 = FStar_UInt128_add(o1, FStar_UInt128_mul_wide(f31, f40));
FStar_UInt128_uint128 o211 = FStar_UInt128_add(o2, FStar_UInt128_mul_wide(f31, f41));
FStar_UInt128_uint128 o31 = FStar_UInt128_add(o3, FStar_UInt128_mul_wide(f31, f42));
FStar_UInt128_uint128 o41 = FStar_UInt128_add(o4, FStar_UInt128_mul_wide(f31, f43));
FStar_UInt128_uint128 o02 = FStar_UInt128_add(o01, FStar_UInt128_mul_wide(f32, tmp23));
FStar_UInt128_uint128 o121 = FStar_UInt128_add(o111, FStar_UInt128_mul_wide(f32, tmp24));
FStar_UInt128_uint128 o221 = FStar_UInt128_add(o211, FStar_UInt128_mul_wide(f32, f40));
FStar_UInt128_uint128 o32 = FStar_UInt128_add(o31, FStar_UInt128_mul_wide(f32, f41));
FStar_UInt128_uint128 o42 = FStar_UInt128_add(o41, FStar_UInt128_mul_wide(f32, f42));
FStar_UInt128_uint128 o03 = FStar_UInt128_add(o02, FStar_UInt128_mul_wide(f33, tmp22));
FStar_UInt128_uint128 o131 = FStar_UInt128_add(o121, FStar_UInt128_mul_wide(f33, tmp23));
FStar_UInt128_uint128 o231 = FStar_UInt128_add(o221, FStar_UInt128_mul_wide(f33, tmp24));
FStar_UInt128_uint128 o33 = FStar_UInt128_add(o32, FStar_UInt128_mul_wide(f33, f40));
FStar_UInt128_uint128 o43 = FStar_UInt128_add(o42, FStar_UInt128_mul_wide(f33, f41));
FStar_UInt128_uint128 o04 = FStar_UInt128_add(o03, FStar_UInt128_mul_wide(f34, tmp21));
FStar_UInt128_uint128 o141 = FStar_UInt128_add(o131, FStar_UInt128_mul_wide(f34, tmp22));
FStar_UInt128_uint128 o241 = FStar_UInt128_add(o231, FStar_UInt128_mul_wide(f34, tmp23));
FStar_UInt128_uint128 o34 = FStar_UInt128_add(o33, FStar_UInt128_mul_wide(f34, tmp24));
FStar_UInt128_uint128 o44 = FStar_UInt128_add(o43, FStar_UInt128_mul_wide(f34, f40));
FStar_UInt128_uint128 tmp_w20 = o04;
FStar_UInt128_uint128 tmp_w21 = o141;
FStar_UInt128_uint128 tmp_w22 = o241;
FStar_UInt128_uint128 tmp_w23 = o34;
FStar_UInt128_uint128 tmp_w24 = o44;
FStar_UInt128_uint128
l_ = FStar_UInt128_add(tmp_w10, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp00 = FStar_UInt128_uint128_to_uint64(l_) & (uint64_t)0x7ffffffffffffU;
uint64_t c00 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_, (uint32_t)51U));
FStar_UInt128_uint128 l_0 = FStar_UInt128_add(tmp_w11, FStar_UInt128_uint64_to_uint128(c00));
uint64_t tmp10 = FStar_UInt128_uint128_to_uint64(l_0) & (uint64_t)0x7ffffffffffffU;
uint64_t c10 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_0, (uint32_t)51U));
FStar_UInt128_uint128 l_1 = FStar_UInt128_add(tmp_w12, FStar_UInt128_uint64_to_uint128(c10));
uint64_t tmp20 = FStar_UInt128_uint128_to_uint64(l_1) & (uint64_t)0x7ffffffffffffU;
uint64_t c20 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_1, (uint32_t)51U));
FStar_UInt128_uint128 l_2 = FStar_UInt128_add(tmp_w13, FStar_UInt128_uint64_to_uint128(c20));
uint64_t tmp30 = FStar_UInt128_uint128_to_uint64(l_2) & (uint64_t)0x7ffffffffffffU;
uint64_t c30 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_2, (uint32_t)51U));
FStar_UInt128_uint128 l_3 = FStar_UInt128_add(tmp_w14, FStar_UInt128_uint64_to_uint128(c30));
uint64_t tmp40 = FStar_UInt128_uint128_to_uint64(l_3) & (uint64_t)0x7ffffffffffffU;
uint64_t c40 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_3, (uint32_t)51U));
uint64_t l_4 = tmp00 + c40 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c50 = l_4 >> (uint32_t)51U;
uint64_t o100 = tmp0_;
uint64_t o112 = tmp10 + c50;
uint64_t o122 = tmp20;
uint64_t o132 = tmp30;
uint64_t o142 = tmp40;
FStar_UInt128_uint128
l_5 = FStar_UInt128_add(tmp_w20, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp0 = FStar_UInt128_uint128_to_uint64(l_5) & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_5, (uint32_t)51U));
FStar_UInt128_uint128 l_6 = FStar_UInt128_add(tmp_w21, FStar_UInt128_uint64_to_uint128(c0));
uint64_t tmp1 = FStar_UInt128_uint128_to_uint64(l_6) & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_6, (uint32_t)51U));
FStar_UInt128_uint128 l_7 = FStar_UInt128_add(tmp_w22, FStar_UInt128_uint64_to_uint128(c1));
uint64_t tmp2 = FStar_UInt128_uint128_to_uint64(l_7) & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_7, (uint32_t)51U));
FStar_UInt128_uint128 l_8 = FStar_UInt128_add(tmp_w23, FStar_UInt128_uint64_to_uint128(c2));
uint64_t tmp3 = FStar_UInt128_uint128_to_uint64(l_8) & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_8, (uint32_t)51U));
FStar_UInt128_uint128 l_9 = FStar_UInt128_add(tmp_w24, FStar_UInt128_uint64_to_uint128(c3));
uint64_t tmp4 = FStar_UInt128_uint128_to_uint64(l_9) & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_9, (uint32_t)51U));
uint64_t l_10 = tmp0 + c4 * (uint64_t)19U;
uint64_t tmp0_0 = l_10 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_10 >> (uint32_t)51U;
uint64_t o200 = tmp0_0;
uint64_t o212 = tmp1 + c5;
uint64_t o222 = tmp2;
uint64_t o232 = tmp3;
uint64_t o242 = tmp4;
uint64_t o10 = o100;
uint64_t o11 = o112;
uint64_t o12 = o122;
uint64_t o13 = o132;
uint64_t o14 = o142;
uint64_t o20 = o200;
uint64_t o21 = o212;
uint64_t o22 = o222;
uint64_t o23 = o232;
uint64_t o24 = o242;
out[0U] = o10;
out[1U] = o11;
out[2U] = o12;
out[3U] = o13;
out[4U] = o14;
out[5U] = o20;
out[6U] = o21;
out[7U] = o22;
out[8U] = o23;
out[9U] = o24;
}
static inline void
Hacl_Impl_Curve25519_Field51_fmul1(uint64_t *out, uint64_t *f1, uint64_t f2)
{
uint64_t f10 = f1[0U];
uint64_t f11 = f1[1U];
uint64_t f12 = f1[2U];
uint64_t f13 = f1[3U];
uint64_t f14 = f1[4U];
FStar_UInt128_uint128 tmp_w0 = FStar_UInt128_mul_wide(f2, f10);
FStar_UInt128_uint128 tmp_w1 = FStar_UInt128_mul_wide(f2, f11);
FStar_UInt128_uint128 tmp_w2 = FStar_UInt128_mul_wide(f2, f12);
FStar_UInt128_uint128 tmp_w3 = FStar_UInt128_mul_wide(f2, f13);
FStar_UInt128_uint128 tmp_w4 = FStar_UInt128_mul_wide(f2, f14);
FStar_UInt128_uint128
l_ = FStar_UInt128_add(tmp_w0, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp0 = FStar_UInt128_uint128_to_uint64(l_) & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_, (uint32_t)51U));
FStar_UInt128_uint128 l_0 = FStar_UInt128_add(tmp_w1, FStar_UInt128_uint64_to_uint128(c0));
uint64_t tmp1 = FStar_UInt128_uint128_to_uint64(l_0) & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_0, (uint32_t)51U));
FStar_UInt128_uint128 l_1 = FStar_UInt128_add(tmp_w2, FStar_UInt128_uint64_to_uint128(c1));
uint64_t tmp2 = FStar_UInt128_uint128_to_uint64(l_1) & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_1, (uint32_t)51U));
FStar_UInt128_uint128 l_2 = FStar_UInt128_add(tmp_w3, FStar_UInt128_uint64_to_uint128(c2));
uint64_t tmp3 = FStar_UInt128_uint128_to_uint64(l_2) & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_2, (uint32_t)51U));
FStar_UInt128_uint128 l_3 = FStar_UInt128_add(tmp_w4, FStar_UInt128_uint64_to_uint128(c3));
uint64_t tmp4 = FStar_UInt128_uint128_to_uint64(l_3) & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_3, (uint32_t)51U));
uint64_t l_4 = tmp0 + c4 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_4 >> (uint32_t)51U;
uint64_t o0 = tmp0_;
uint64_t o1 = tmp1 + c5;
uint64_t o2 = tmp2;
uint64_t o3 = tmp3;
uint64_t o4 = tmp4;
out[0U] = o0;
out[1U] = o1;
out[2U] = o2;
out[3U] = o3;
out[4U] = o4;
}
static inline void
Hacl_Impl_Curve25519_Field51_fsqr(uint64_t *out, uint64_t *f, FStar_UInt128_uint128 *uu___)
{
uint64_t f0 = f[0U];
uint64_t f1 = f[1U];
uint64_t f2 = f[2U];
uint64_t f3 = f[3U];
uint64_t f4 = f[4U];
uint64_t d0 = (uint64_t)2U * f0;
uint64_t d1 = (uint64_t)2U * f1;
uint64_t d2 = (uint64_t)38U * f2;
uint64_t d3 = (uint64_t)19U * f3;
uint64_t d419 = (uint64_t)19U * f4;
uint64_t d4 = (uint64_t)2U * d419;
FStar_UInt128_uint128
s0 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(f0, f0),
FStar_UInt128_mul_wide(d4, f1)),
FStar_UInt128_mul_wide(d2, f3));
FStar_UInt128_uint128
s1 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f1),
FStar_UInt128_mul_wide(d4, f2)),
FStar_UInt128_mul_wide(d3, f3));
FStar_UInt128_uint128
s2 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f2),
FStar_UInt128_mul_wide(f1, f1)),
FStar_UInt128_mul_wide(d4, f3));
FStar_UInt128_uint128
s3 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f3),
FStar_UInt128_mul_wide(d1, f2)),
FStar_UInt128_mul_wide(f4, d419));
FStar_UInt128_uint128
s4 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f4),
FStar_UInt128_mul_wide(d1, f3)),
FStar_UInt128_mul_wide(f2, f2));
FStar_UInt128_uint128 o00 = s0;
FStar_UInt128_uint128 o10 = s1;
FStar_UInt128_uint128 o20 = s2;
FStar_UInt128_uint128 o30 = s3;
FStar_UInt128_uint128 o40 = s4;
FStar_UInt128_uint128
l_ = FStar_UInt128_add(o00, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp0 = FStar_UInt128_uint128_to_uint64(l_) & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_, (uint32_t)51U));
FStar_UInt128_uint128 l_0 = FStar_UInt128_add(o10, FStar_UInt128_uint64_to_uint128(c0));
uint64_t tmp1 = FStar_UInt128_uint128_to_uint64(l_0) & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_0, (uint32_t)51U));
FStar_UInt128_uint128 l_1 = FStar_UInt128_add(o20, FStar_UInt128_uint64_to_uint128(c1));
uint64_t tmp2 = FStar_UInt128_uint128_to_uint64(l_1) & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_1, (uint32_t)51U));
FStar_UInt128_uint128 l_2 = FStar_UInt128_add(o30, FStar_UInt128_uint64_to_uint128(c2));
uint64_t tmp3 = FStar_UInt128_uint128_to_uint64(l_2) & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_2, (uint32_t)51U));
FStar_UInt128_uint128 l_3 = FStar_UInt128_add(o40, FStar_UInt128_uint64_to_uint128(c3));
uint64_t tmp4 = FStar_UInt128_uint128_to_uint64(l_3) & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_3, (uint32_t)51U));
uint64_t l_4 = tmp0 + c4 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_4 >> (uint32_t)51U;
uint64_t o0 = tmp0_;
uint64_t o1 = tmp1 + c5;
uint64_t o2 = tmp2;
uint64_t o3 = tmp3;
uint64_t o4 = tmp4;
out[0U] = o0;
out[1U] = o1;
out[2U] = o2;
out[3U] = o3;
out[4U] = o4;
}
static inline void
Hacl_Impl_Curve25519_Field51_fsqr2(uint64_t *out, uint64_t *f, FStar_UInt128_uint128 *uu___)
{
uint64_t f10 = f[0U];
uint64_t f11 = f[1U];
uint64_t f12 = f[2U];
uint64_t f13 = f[3U];
uint64_t f14 = f[4U];
uint64_t f20 = f[5U];
uint64_t f21 = f[6U];
uint64_t f22 = f[7U];
uint64_t f23 = f[8U];
uint64_t f24 = f[9U];
uint64_t d00 = (uint64_t)2U * f10;
uint64_t d10 = (uint64_t)2U * f11;
uint64_t d20 = (uint64_t)38U * f12;
uint64_t d30 = (uint64_t)19U * f13;
uint64_t d4190 = (uint64_t)19U * f14;
uint64_t d40 = (uint64_t)2U * d4190;
FStar_UInt128_uint128
s00 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(f10, f10),
FStar_UInt128_mul_wide(d40, f11)),
FStar_UInt128_mul_wide(d20, f13));
FStar_UInt128_uint128
s10 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d00, f11),
FStar_UInt128_mul_wide(d40, f12)),
FStar_UInt128_mul_wide(d30, f13));
FStar_UInt128_uint128
s20 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d00, f12),
FStar_UInt128_mul_wide(f11, f11)),
FStar_UInt128_mul_wide(d40, f13));
FStar_UInt128_uint128
s30 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d00, f13),
FStar_UInt128_mul_wide(d10, f12)),
FStar_UInt128_mul_wide(f14, d4190));
FStar_UInt128_uint128
s40 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d00, f14),
FStar_UInt128_mul_wide(d10, f13)),
FStar_UInt128_mul_wide(f12, f12));
FStar_UInt128_uint128 o100 = s00;
FStar_UInt128_uint128 o110 = s10;
FStar_UInt128_uint128 o120 = s20;
FStar_UInt128_uint128 o130 = s30;
FStar_UInt128_uint128 o140 = s40;
uint64_t d0 = (uint64_t)2U * f20;
uint64_t d1 = (uint64_t)2U * f21;
uint64_t d2 = (uint64_t)38U * f22;
uint64_t d3 = (uint64_t)19U * f23;
uint64_t d419 = (uint64_t)19U * f24;
uint64_t d4 = (uint64_t)2U * d419;
FStar_UInt128_uint128
s0 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(f20, f20),
FStar_UInt128_mul_wide(d4, f21)),
FStar_UInt128_mul_wide(d2, f23));
FStar_UInt128_uint128
s1 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f21),
FStar_UInt128_mul_wide(d4, f22)),
FStar_UInt128_mul_wide(d3, f23));
FStar_UInt128_uint128
s2 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f22),
FStar_UInt128_mul_wide(f21, f21)),
FStar_UInt128_mul_wide(d4, f23));
FStar_UInt128_uint128
s3 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f23),
FStar_UInt128_mul_wide(d1, f22)),
FStar_UInt128_mul_wide(f24, d419));
FStar_UInt128_uint128
s4 =
FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, f24),
FStar_UInt128_mul_wide(d1, f23)),
FStar_UInt128_mul_wide(f22, f22));
FStar_UInt128_uint128 o200 = s0;
FStar_UInt128_uint128 o210 = s1;
FStar_UInt128_uint128 o220 = s2;
FStar_UInt128_uint128 o230 = s3;
FStar_UInt128_uint128 o240 = s4;
FStar_UInt128_uint128
l_ = FStar_UInt128_add(o100, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp00 = FStar_UInt128_uint128_to_uint64(l_) & (uint64_t)0x7ffffffffffffU;
uint64_t c00 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_, (uint32_t)51U));
FStar_UInt128_uint128 l_0 = FStar_UInt128_add(o110, FStar_UInt128_uint64_to_uint128(c00));
uint64_t tmp10 = FStar_UInt128_uint128_to_uint64(l_0) & (uint64_t)0x7ffffffffffffU;
uint64_t c10 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_0, (uint32_t)51U));
FStar_UInt128_uint128 l_1 = FStar_UInt128_add(o120, FStar_UInt128_uint64_to_uint128(c10));
uint64_t tmp20 = FStar_UInt128_uint128_to_uint64(l_1) & (uint64_t)0x7ffffffffffffU;
uint64_t c20 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_1, (uint32_t)51U));
FStar_UInt128_uint128 l_2 = FStar_UInt128_add(o130, FStar_UInt128_uint64_to_uint128(c20));
uint64_t tmp30 = FStar_UInt128_uint128_to_uint64(l_2) & (uint64_t)0x7ffffffffffffU;
uint64_t c30 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_2, (uint32_t)51U));
FStar_UInt128_uint128 l_3 = FStar_UInt128_add(o140, FStar_UInt128_uint64_to_uint128(c30));
uint64_t tmp40 = FStar_UInt128_uint128_to_uint64(l_3) & (uint64_t)0x7ffffffffffffU;
uint64_t c40 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_3, (uint32_t)51U));
uint64_t l_4 = tmp00 + c40 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c50 = l_4 >> (uint32_t)51U;
uint64_t o101 = tmp0_;
uint64_t o111 = tmp10 + c50;
uint64_t o121 = tmp20;
uint64_t o131 = tmp30;
uint64_t o141 = tmp40;
FStar_UInt128_uint128
l_5 = FStar_UInt128_add(o200, FStar_UInt128_uint64_to_uint128((uint64_t)0U));
uint64_t tmp0 = FStar_UInt128_uint128_to_uint64(l_5) & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_5, (uint32_t)51U));
FStar_UInt128_uint128 l_6 = FStar_UInt128_add(o210, FStar_UInt128_uint64_to_uint128(c0));
uint64_t tmp1 = FStar_UInt128_uint128_to_uint64(l_6) & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_6, (uint32_t)51U));
FStar_UInt128_uint128 l_7 = FStar_UInt128_add(o220, FStar_UInt128_uint64_to_uint128(c1));
uint64_t tmp2 = FStar_UInt128_uint128_to_uint64(l_7) & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_7, (uint32_t)51U));
FStar_UInt128_uint128 l_8 = FStar_UInt128_add(o230, FStar_UInt128_uint64_to_uint128(c2));
uint64_t tmp3 = FStar_UInt128_uint128_to_uint64(l_8) & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_8, (uint32_t)51U));
FStar_UInt128_uint128 l_9 = FStar_UInt128_add(o240, FStar_UInt128_uint64_to_uint128(c3));
uint64_t tmp4 = FStar_UInt128_uint128_to_uint64(l_9) & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(l_9, (uint32_t)51U));
uint64_t l_10 = tmp0 + c4 * (uint64_t)19U;
uint64_t tmp0_0 = l_10 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_10 >> (uint32_t)51U;
uint64_t o201 = tmp0_0;
uint64_t o211 = tmp1 + c5;
uint64_t o221 = tmp2;
uint64_t o231 = tmp3;
uint64_t o241 = tmp4;
uint64_t o10 = o101;
uint64_t o11 = o111;
uint64_t o12 = o121;
uint64_t o13 = o131;
uint64_t o14 = o141;
uint64_t o20 = o201;
uint64_t o21 = o211;
uint64_t o22 = o221;
uint64_t o23 = o231;
uint64_t o24 = o241;
out[0U] = o10;
out[1U] = o11;
out[2U] = o12;
out[3U] = o13;
out[4U] = o14;
out[5U] = o20;
out[6U] = o21;
out[7U] = o22;
out[8U] = o23;
out[9U] = o24;
}
static inline void
Hacl_Impl_Curve25519_Field51_store_felem(uint64_t *u64s, uint64_t *f)
{
uint64_t f0 = f[0U];
uint64_t f1 = f[1U];
uint64_t f2 = f[2U];
uint64_t f3 = f[3U];
uint64_t f4 = f[4U];
uint64_t l_ = f0 + (uint64_t)0U;
uint64_t tmp0 = l_ & (uint64_t)0x7ffffffffffffU;
uint64_t c0 = l_ >> (uint32_t)51U;
uint64_t l_0 = f1 + c0;
uint64_t tmp1 = l_0 & (uint64_t)0x7ffffffffffffU;
uint64_t c1 = l_0 >> (uint32_t)51U;
uint64_t l_1 = f2 + c1;
uint64_t tmp2 = l_1 & (uint64_t)0x7ffffffffffffU;
uint64_t c2 = l_1 >> (uint32_t)51U;
uint64_t l_2 = f3 + c2;
uint64_t tmp3 = l_2 & (uint64_t)0x7ffffffffffffU;
uint64_t c3 = l_2 >> (uint32_t)51U;
uint64_t l_3 = f4 + c3;
uint64_t tmp4 = l_3 & (uint64_t)0x7ffffffffffffU;
uint64_t c4 = l_3 >> (uint32_t)51U;
uint64_t l_4 = tmp0 + c4 * (uint64_t)19U;
uint64_t tmp0_ = l_4 & (uint64_t)0x7ffffffffffffU;
uint64_t c5 = l_4 >> (uint32_t)51U;
uint64_t f01 = tmp0_;
uint64_t f11 = tmp1 + c5;
uint64_t f21 = tmp2;
uint64_t f31 = tmp3;
uint64_t f41 = tmp4;
uint64_t m0 = FStar_UInt64_gte_mask(f01, (uint64_t)0x7ffffffffffedU);
uint64_t m1 = FStar_UInt64_eq_mask(f11, (uint64_t)0x7ffffffffffffU);
uint64_t m2 = FStar_UInt64_eq_mask(f21, (uint64_t)0x7ffffffffffffU);
uint64_t m3 = FStar_UInt64_eq_mask(f31, (uint64_t)0x7ffffffffffffU);
uint64_t m4 = FStar_UInt64_eq_mask(f41, (uint64_t)0x7ffffffffffffU);
uint64_t mask = (((m0 & m1) & m2) & m3) & m4;
uint64_t f0_ = f01 - (mask & (uint64_t)0x7ffffffffffedU);
uint64_t f1_ = f11 - (mask & (uint64_t)0x7ffffffffffffU);
uint64_t f2_ = f21 - (mask & (uint64_t)0x7ffffffffffffU);
uint64_t f3_ = f31 - (mask & (uint64_t)0x7ffffffffffffU);
uint64_t f4_ = f41 - (mask & (uint64_t)0x7ffffffffffffU);
uint64_t f02 = f0_;
uint64_t f12 = f1_;
uint64_t f22 = f2_;
uint64_t f32 = f3_;
uint64_t f42 = f4_;
uint64_t o00 = f02 | f12 << (uint32_t)51U;
uint64_t o10 = f12 >> (uint32_t)13U | f22 << (uint32_t)38U;
uint64_t o20 = f22 >> (uint32_t)26U | f32 << (uint32_t)25U;
uint64_t o30 = f32 >> (uint32_t)39U | f42 << (uint32_t)12U;
uint64_t o0 = o00;
uint64_t o1 = o10;
uint64_t o2 = o20;
uint64_t o3 = o30;
u64s[0U] = o0;
u64s[1U] = o1;
u64s[2U] = o2;
u64s[3U] = o3;
}
static inline void
Hacl_Impl_Curve25519_Field51_cswap2(uint64_t bit, uint64_t *p1, uint64_t *p2)
{
uint64_t mask = (uint64_t)0U - bit;
KRML_MAYBE_FOR10(i,
(uint32_t)0U,
(uint32_t)10U,
(uint32_t)1U,
uint64_t dummy = mask & (p1[i] ^ p2[i]);
p1[i] = p1[i] ^ dummy;
p2[i] = p2[i] ^ dummy;);
}
#if defined(__cplusplus)
}
#endif
#define __Hacl_Bignum25519_51_H_DEFINED
#endif

View file

@ -1,270 +1,226 @@
/* Copyright 2016-2018 INRIA and Microsoft Corporation
/* MIT License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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:
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.
*/
#include "Hacl_Chacha20.h"
#include "internal/Hacl_Chacha20.h"
static void
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(uint32_t *output, uint8_t *input, uint32_t len)
const uint32_t
Hacl_Impl_Chacha20_Vec_chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
static inline void
quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint8_t *x0 = input + (uint32_t)4U * i;
uint32_t inputi = load32_le(x0);
output[i] = inputi;
}
uint32_t sta = st[a];
uint32_t stb0 = st[b];
uint32_t std0 = st[d];
uint32_t sta10 = sta + stb0;
uint32_t std10 = std0 ^ sta10;
uint32_t std2 = std10 << (uint32_t)16U | std10 >> (uint32_t)16U;
st[a] = sta10;
st[d] = std2;
uint32_t sta0 = st[c];
uint32_t stb1 = st[d];
uint32_t std3 = st[b];
uint32_t sta11 = sta0 + stb1;
uint32_t std11 = std3 ^ sta11;
uint32_t std20 = std11 << (uint32_t)12U | std11 >> (uint32_t)20U;
st[c] = sta11;
st[b] = std20;
uint32_t sta2 = st[a];
uint32_t stb2 = st[b];
uint32_t std4 = st[d];
uint32_t sta12 = sta2 + stb2;
uint32_t std12 = std4 ^ sta12;
uint32_t std21 = std12 << (uint32_t)8U | std12 >> (uint32_t)24U;
st[a] = sta12;
st[d] = std21;
uint32_t sta3 = st[c];
uint32_t stb = st[d];
uint32_t std = st[b];
uint32_t sta1 = sta3 + stb;
uint32_t std1 = std ^ sta1;
uint32_t std22 = std1 << (uint32_t)7U | std1 >> (uint32_t)25U;
st[c] = sta1;
st[b] = std22;
}
static inline void
double_round(uint32_t *st)
{
quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
}
static inline void
rounds(uint32_t *st)
{
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
double_round(st);
}
static inline void
chacha20_core(uint32_t *k, uint32_t *ctx, uint32_t ctr)
{
memcpy(k, ctx, (uint32_t)16U * sizeof(uint32_t));
uint32_t ctr_u32 = ctr;
k[12U] = k[12U] + ctr_u32;
rounds(k);
KRML_MAYBE_FOR16(i,
(uint32_t)0U,
(uint32_t)16U,
(uint32_t)1U,
uint32_t *os = k;
uint32_t x = k[i] + ctx[i];
os[i] = x;);
k[12U] = k[12U] + ctr_u32;
}
static const uint32_t
chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
void
Hacl_Impl_Chacha20_chacha20_init(uint32_t *ctx, uint8_t *k, uint8_t *n, uint32_t ctr)
{
KRML_MAYBE_FOR4(i,
(uint32_t)0U,
(uint32_t)4U,
(uint32_t)1U,
uint32_t *os = ctx;
uint32_t x = chacha20_constants[i];
os[i] = x;);
KRML_MAYBE_FOR8(i,
(uint32_t)0U,
(uint32_t)8U,
(uint32_t)1U,
uint32_t *os = ctx + (uint32_t)4U;
uint8_t *bj = k + i * (uint32_t)4U;
uint32_t u = load32_le(bj);
uint32_t r = u;
uint32_t x = r;
os[i] = x;);
ctx[12U] = ctr;
KRML_MAYBE_FOR3(i,
(uint32_t)0U,
(uint32_t)3U,
(uint32_t)1U,
uint32_t *os = ctx + (uint32_t)13U;
uint8_t *bj = n + i * (uint32_t)4U;
uint32_t u = load32_le(bj);
uint32_t r = u;
uint32_t x = r;
os[i] = x;);
}
static void
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(uint8_t *output, uint32_t *input, uint32_t len)
chacha20_encrypt_block(uint32_t *ctx, uint8_t *out, uint32_t incr, uint8_t *text)
{
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint32_t hd1 = input[i];
uint8_t *x0 = output + (uint32_t)4U * i;
store32_le(x0, hd1);
}
uint32_t k[16U] = { 0U };
chacha20_core(k, ctx, incr);
uint32_t bl[16U] = { 0U };
KRML_MAYBE_FOR16(i,
(uint32_t)0U,
(uint32_t)16U,
(uint32_t)1U,
uint32_t *os = bl;
uint8_t *bj = text + i * (uint32_t)4U;
uint32_t u = load32_le(bj);
uint32_t r = u;
uint32_t x = r;
os[i] = x;);
KRML_MAYBE_FOR16(i,
(uint32_t)0U,
(uint32_t)16U,
(uint32_t)1U,
uint32_t *os = bl;
uint32_t x = bl[i] ^ k[i];
os[i] = x;);
KRML_MAYBE_FOR16(i,
(uint32_t)0U,
(uint32_t)16U,
(uint32_t)1U,
store32_le(out + i * (uint32_t)4U, bl[i]););
}
inline static uint32_t
Hacl_Impl_Chacha20_rotate_left(uint32_t a, uint32_t s)
static inline void
chacha20_encrypt_last(uint32_t *ctx, uint32_t len, uint8_t *out, uint32_t incr, uint8_t *text)
{
return a << s | a >> ((uint32_t)32U - s);
}
inline static void
Hacl_Impl_Chacha20_quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
uint32_t sa = st[a];
uint32_t sb0 = st[b];
st[a] = sa + sb0;
uint32_t sd = st[d];
uint32_t sa10 = st[a];
uint32_t sda = sd ^ sa10;
st[d] = Hacl_Impl_Chacha20_rotate_left(sda, (uint32_t)16U);
uint32_t sa0 = st[c];
uint32_t sb1 = st[d];
st[c] = sa0 + sb1;
uint32_t sd0 = st[b];
uint32_t sa11 = st[c];
uint32_t sda0 = sd0 ^ sa11;
st[b] = Hacl_Impl_Chacha20_rotate_left(sda0, (uint32_t)12U);
uint32_t sa2 = st[a];
uint32_t sb2 = st[b];
st[a] = sa2 + sb2;
uint32_t sd1 = st[d];
uint32_t sa12 = st[a];
uint32_t sda1 = sd1 ^ sa12;
st[d] = Hacl_Impl_Chacha20_rotate_left(sda1, (uint32_t)8U);
uint32_t sa3 = st[c];
uint32_t sb = st[d];
st[c] = sa3 + sb;
uint32_t sd2 = st[b];
uint32_t sa1 = st[c];
uint32_t sda2 = sd2 ^ sa1;
st[b] = Hacl_Impl_Chacha20_rotate_left(sda2, (uint32_t)7U);
}
inline static void
Hacl_Impl_Chacha20_double_round(uint32_t *st)
{
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
Hacl_Impl_Chacha20_quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
}
inline static void
Hacl_Impl_Chacha20_rounds(uint32_t *st)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)10U; i = i + (uint32_t)1U)
Hacl_Impl_Chacha20_double_round(st);
}
inline static void
Hacl_Impl_Chacha20_sum_states(uint32_t *st, uint32_t *st_)
{
for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i = i + (uint32_t)1U) {
uint32_t xi = st[i];
uint32_t yi = st_[i];
st[i] = xi + yi;
}
}
inline static void
Hacl_Impl_Chacha20_copy_state(uint32_t *st, uint32_t *st_)
{
memcpy(st, st_, (uint32_t)16U * sizeof st_[0U]);
}
inline static void
Hacl_Impl_Chacha20_chacha20_core(uint32_t *k, uint32_t *st, uint32_t ctr)
{
st[12U] = ctr;
Hacl_Impl_Chacha20_copy_state(k, st);
Hacl_Impl_Chacha20_rounds(k);
Hacl_Impl_Chacha20_sum_states(k, st);
}
inline static void
Hacl_Impl_Chacha20_chacha20_block(uint8_t *stream_block, uint32_t *st, uint32_t ctr)
{
uint32_t st_[16U] = { 0U };
Hacl_Impl_Chacha20_chacha20_core(st_, st, ctr);
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(stream_block, st_, (uint32_t)16U);
}
inline static void
Hacl_Impl_Chacha20_init(uint32_t *st, uint8_t *k, uint8_t *n1)
{
uint32_t *stcst = st;
uint32_t *stk = st + (uint32_t)4U;
uint32_t *stc = st + (uint32_t)12U;
uint32_t *stn = st + (uint32_t)13U;
stcst[0U] = (uint32_t)0x61707865U;
stcst[1U] = (uint32_t)0x3320646eU;
stcst[2U] = (uint32_t)0x79622d32U;
stcst[3U] = (uint32_t)0x6b206574U;
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stk, k, (uint32_t)8U);
stc[0U] = (uint32_t)0U;
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(stn, n1, (uint32_t)3U);
}
static void
Hacl_Impl_Chacha20_update(uint8_t *output, uint8_t *plain, uint32_t *st, uint32_t ctr)
{
uint32_t b[48U] = { 0U };
uint32_t *k = b;
uint32_t *ib = b + (uint32_t)16U;
uint32_t *ob = b + (uint32_t)32U;
Hacl_Impl_Chacha20_chacha20_core(k, st, ctr);
Hacl_Lib_LoadStore32_uint32s_from_le_bytes(ib, plain, (uint32_t)16U);
for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i = i + (uint32_t)1U) {
uint32_t xi = ib[i];
uint32_t yi = k[i];
ob[i] = xi ^ yi;
}
Hacl_Lib_LoadStore32_uint32s_to_le_bytes(output, ob, (uint32_t)16U);
}
static void
Hacl_Impl_Chacha20_update_last(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint32_t *st,
uint32_t ctr)
{
uint8_t block[64U] = { 0U };
Hacl_Impl_Chacha20_chacha20_block(block, st, ctr);
uint8_t *mask = block;
for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) {
uint8_t xi = plain[i];
uint8_t yi = mask[i];
output[i] = xi ^ yi;
}
}
static void
Hacl_Impl_Chacha20_chacha20_counter_mode_blocks(
uint8_t *output,
uint8_t *plain,
uint32_t num_blocks,
uint32_t *st,
uint32_t ctr)
{
for (uint32_t i = (uint32_t)0U; i < num_blocks; i = i + (uint32_t)1U) {
uint8_t *b = plain + (uint32_t)64U * i;
uint8_t *o = output + (uint32_t)64U * i;
Hacl_Impl_Chacha20_update(o, b, st, ctr + i);
}
}
static void
Hacl_Impl_Chacha20_chacha20_counter_mode(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint32_t *st,
uint32_t ctr)
{
uint32_t blocks_len = len >> (uint32_t)6U;
uint32_t part_len = len & (uint32_t)0x3fU;
uint8_t *output_ = output;
uint8_t *plain_ = plain;
uint8_t *output__ = output + (uint32_t)64U * blocks_len;
uint8_t *plain__ = plain + (uint32_t)64U * blocks_len;
Hacl_Impl_Chacha20_chacha20_counter_mode_blocks(output_, plain_, blocks_len, st, ctr);
if (part_len > (uint32_t)0U)
Hacl_Impl_Chacha20_update_last(output__, plain__, part_len, st, ctr + blocks_len);
}
static void
Hacl_Impl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint32_t ctr)
{
uint32_t buf[16U] = { 0U };
uint32_t *st = buf;
Hacl_Impl_Chacha20_init(st, k, n1);
Hacl_Impl_Chacha20_chacha20_counter_mode(output, plain, len, st, ctr);
uint8_t plain[64U] = { 0U };
memcpy(plain, text, len * sizeof(uint8_t));
chacha20_encrypt_block(ctx, plain, incr, plain);
memcpy(out, plain, len * sizeof(uint8_t));
}
void
Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr)
Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text)
{
uint32_t buf[16U] = { 0U };
uint32_t *st = buf;
Hacl_Impl_Chacha20_init(st, k, n1);
Hacl_Impl_Chacha20_chacha20_block(block, st, ctr);
uint32_t rem = len % (uint32_t)64U;
uint32_t nb = len / (uint32_t)64U;
uint32_t rem1 = len % (uint32_t)64U;
for (uint32_t i = (uint32_t)0U; i < nb; i++) {
chacha20_encrypt_block(ctx, out + i * (uint32_t)64U, i, text + i * (uint32_t)64U);
}
if (rem1 > (uint32_t)0U) {
chacha20_encrypt_last(ctx, rem, out + nb * (uint32_t)64U, nb, text + nb * (uint32_t)64U);
}
}
/*
This function implements Chacha20
val chacha20 :
output:uint8_p ->
plain:uint8_p{ disjoint output plain } ->
len:uint32_t{ v len = length output /\ v len = length plain } ->
key:uint8_p{ length key = 32 } ->
nonce:uint8_p{ length nonce = 12 } ->
ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
Stack unit
(requires
fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
(ensures
fun h0 _ h1 ->
live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
live h0 nonce /\
live h0 key /\
h1.[ output ] ==
chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
*/
void
Hacl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
Hacl_Chacha20_chacha20_encrypt(
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint8_t *out,
uint8_t *text,
uint8_t *key,
uint8_t *n,
uint32_t ctr)
{
Hacl_Impl_Chacha20_chacha20(output, plain, len, k, n1, ctr);
uint32_t ctx[16U] = { 0U };
Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, text);
}
void
Hacl_Chacha20_chacha20_decrypt(
uint32_t len,
uint8_t *out,
uint8_t *cipher,
uint8_t *key,
uint8_t *n,
uint32_t ctr)
{
uint32_t ctx[16U] = { 0U };
Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, cipher);
}

View file

@ -1,81 +1,61 @@
/* Copyright 2016-2018 INRIA and Microsoft Corporation
/* MIT License
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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:
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.
*/
#include "kremlib.h"
#ifndef __Hacl_Chacha20_H
#define __Hacl_Chacha20_H
typedef uint32_t Hacl_Impl_Xor_Lemmas_u32;
typedef uint8_t Hacl_Impl_Xor_Lemmas_u8;
typedef uint8_t *Hacl_Lib_LoadStore32_uint8_p;
typedef uint32_t Hacl_Impl_Chacha20_u32;
typedef uint32_t Hacl_Impl_Chacha20_h32;
typedef uint8_t *Hacl_Impl_Chacha20_uint8_p;
typedef uint32_t *Hacl_Impl_Chacha20_state;
typedef uint32_t Hacl_Impl_Chacha20_idx;
typedef struct
{
void *k;
void *n;
} Hacl_Impl_Chacha20_log_t_;
typedef void *Hacl_Impl_Chacha20_log_t;
typedef uint32_t Hacl_Lib_Create_h32;
typedef uint8_t *Hacl_Chacha20_uint8_p;
typedef uint32_t Hacl_Chacha20_uint32_t;
void Hacl_Chacha20_chacha20_key_block(uint8_t *block, uint8_t *k, uint8_t *n1, uint32_t ctr);
/*
This function implements Chacha20
val chacha20 :
output:uint8_p ->
plain:uint8_p{ disjoint output plain } ->
len:uint32_t{ v len = length output /\ v len = length plain } ->
key:uint8_p{ length key = 32 } ->
nonce:uint8_p{ length nonce = 12 } ->
ctr:uint32_t{ v ctr + length plain / 64 < pow2 32 } ->
Stack unit
(requires
fun h -> live h output /\ live h plain /\ live h nonce /\ live h key)
(ensures
fun h0 _ h1 ->
live h1 output /\ live h0 plain /\ modifies_1 output h0 h1 /\
live h0 nonce /\
live h0 key /\
h1.[ output ] ==
chacha20_encrypt_bytes h0.[ key ] h0.[ nonce ] (v ctr) h0.[ plain ])
*/
void
Hacl_Chacha20_chacha20(
uint8_t *output,
uint8_t *plain,
uint32_t len,
uint8_t *k,
uint8_t *n1,
uint32_t ctr);
#if defined(__cplusplus)
extern "C" {
#endif
#include <string.h>
#include "krml/internal/types.h"
#include "krml/lowstar_endianness.h"
#include "krml/internal/target.h"
#include "Hacl_Krmllib.h"
void
Hacl_Chacha20_chacha20_encrypt(
uint32_t len,
uint8_t *out,
uint8_t *text,
uint8_t *key,
uint8_t *n,
uint32_t ctr);
void
Hacl_Chacha20_chacha20_decrypt(
uint32_t len,
uint8_t *out,
uint8_t *cipher,
uint8_t *key,
uint8_t *n,
uint32_t ctr);
#if defined(__cplusplus)
}
#endif
#define __Hacl_Chacha20_H_DEFINED
#endif

Some files were not shown because too many files have changed in this diff Show more