Compare commits
1 Commits
WIN64_MASM
...
src
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
258dc9fead |
@@ -1,602 +0,0 @@
|
||||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Stephen Fung <fungstep@hotmail.com> and
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
-include config.mk
|
||||
|
||||
# default for all platforms
|
||||
# unset this on those that have multiple freebl libraries
|
||||
FREEBL_BUILD_SINGLE_SHLIB = 1
|
||||
|
||||
ifdef USE_64
|
||||
DEFINES += -DNSS_USE_64
|
||||
endif
|
||||
|
||||
ifdef USE_ABI32_FPU
|
||||
DEFINES += -DNSS_USE_ABI32_FPU
|
||||
endif
|
||||
|
||||
# des.c wants _X86_ defined for intel CPUs.
|
||||
# coreconf does this for windows, but not for Linux, FreeBSD, etc.
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ifneq (,$(filter-out WIN%,$(OS_TARGET)))
|
||||
OS_REL_CFLAGS += -D_X86_
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),OSF1)
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_NO_MP_WORD
|
||||
MPI_SRCS += mpvalpha.c
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out WINNT WIN95,$(OS_TARGET))) #omits WIN16 and WINCE
|
||||
ifndef USE_64
|
||||
# 32-bit Windows
|
||||
ifdef NS_USE_GCC
|
||||
# Ideally, we want to use assembler
|
||||
# ASFILES = mpi_x86.s
|
||||
# DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE \
|
||||
# -DMP_ASSEMBLY_DIV_2DX1D
|
||||
# but we haven't figured out how to make it work, so we are not
|
||||
# using assembler right now.
|
||||
ASFILES =
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT
|
||||
else
|
||||
# MSVC
|
||||
MPI_SRCS += mpi_x86_asm.c
|
||||
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
|
||||
endif
|
||||
endif
|
||||
else
|
||||
# 64-bit Windows
|
||||
# MPI_SRCS += mpi_x86_asm.c
|
||||
# DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
# DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
# DEFINES += -DMP_USE_UINT_DIGIT
|
||||
# -DMP_NO_MP_WORD
|
||||
ifdef BUILD_OPT
|
||||
OPTIMIZER += -Ox # maximum optimization for freebl
|
||||
endif
|
||||
ASFILES = arcfour-amd64-masm.asm mpi_amd64_masm.asm mp_comba_amd64_masm.asm
|
||||
ASFILES += mpcpucache_amd64_masm.asm
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
MPI_SRCS += mpi_amd64.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),WINCE)
|
||||
DEFINES += -DMP_ARGCHK=0 # no assert in WinCE
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
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),Linux)
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
|
||||
ASFLAGS += -march=opteron -m64 -fPIC
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# DEFINES += -DMPI_AMD64_ADD
|
||||
MPI_SRCS += mpi_amd64.c mp_comba.c
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
ASFILES = mpi_x86.s
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
|
||||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# The floating point ECC code doesn't work on Linux x86 (bug 311432).
|
||||
#ECL_USE_FP = 1
|
||||
endif
|
||||
endif # Linux
|
||||
|
||||
ifeq ($(OS_TARGET),AIX)
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
ifndef USE_64
|
||||
DEFINES += -DMP_NO_DIV_WORD -DMP_NO_ADD_WORD -DMP_NO_SUB_WORD
|
||||
endif
|
||||
endif # AIX
|
||||
|
||||
ifeq ($(OS_TARGET), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
# PA-RISC
|
||||
ASFILES += ret_cr16.s
|
||||
ifndef USE_64
|
||||
FREEBL_BUILD_SINGLE_SHLIB =
|
||||
HAVE_ABI32_INT32 = 1
|
||||
HAVE_ABI32_FPU = 1
|
||||
endif
|
||||
ifdef FREEBL_CHILD_BUILD
|
||||
ifdef USE_ABI32_INT32
|
||||
# build for DA1.1 (HP PA 1.1) 32-bit ABI build with 32-bit arithmetic
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
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
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
else
|
||||
# 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
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
ARCHFLAG = -Aa +e +DA2.0 +DS2.0
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# The blapi functions are defined not only in the freebl shared
|
||||
# libraries but also in the shared libraries linked with loader.c
|
||||
# (libsoftokn3.so and libssl3.so). We need to use GNU ld's
|
||||
# -Bsymbolic option or the equivalent option for other linkers
|
||||
# to bind the blapi function references in FREEBLVector vector
|
||||
# (ldvector.c) to the blapi functions defined in the freebl
|
||||
# shared libraries.
|
||||
ifeq (,$(filter-out BSD_OS FreeBSD Linux NetBSD OpenBSD, $(OS_TARGET)))
|
||||
MKSHLIB += -Wl,-Bsymbolic
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),SunOS)
|
||||
|
||||
# The -R '$ORIGIN' linker option instructs this library to search for its
|
||||
# dependencies in the same directory where it resides.
|
||||
MKSHLIB += -R '$$ORIGIN'
|
||||
ifdef NS_USE_GCC
|
||||
ifdef GCC_USE_GNU_LD
|
||||
MKSHLIB += -Wl,-Bsymbolic,-z,now,-z,text
|
||||
else
|
||||
MKSHLIB += -Wl,-B,symbolic,-z,now,-z,text
|
||||
endif # GCC_USE_GNU_LD
|
||||
else
|
||||
MKSHLIB += -B symbolic -z now -z text
|
||||
endif # NS_USE_GCC
|
||||
|
||||
# Sun's WorkShop defines v8, v8plus and v9 architectures.
|
||||
# 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.
|
||||
ifeq ($(CPU_ARCH),sparc)
|
||||
FREEBL_BUILD_SINGLE_SHLIB=
|
||||
ifdef USE_64
|
||||
HAVE_ABI64_INT = 1
|
||||
HAVE_ABI64_FPU = 1
|
||||
else
|
||||
HAVE_ABI32_INT32 = 1
|
||||
HAVE_ABI32_FPU = 1
|
||||
HAVE_ABI32_INT64 = 1
|
||||
endif
|
||||
SYSV_SPARC = 1
|
||||
SOLARIS_AS = /usr/ccs/bin/as
|
||||
#### set arch, asm, c flags
|
||||
ifdef NS_USE_GCC
|
||||
ifdef USE_ABI32_INT32
|
||||
# default ARCHFLAG=-mcpu=v8 set by coreconf/sunOS5.mk
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plus
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plusa
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
endif # USE_ABI32_FPU
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
ARCHFLAG += -mcpu=v9 -Wa,-xarch=v9
|
||||
SOLARIS_AS_FLAGS = -xarch=v9 -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size
|
||||
ARCHFLAG += -mcpu=v9 -Wa,-xarch=v9a
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
endif
|
||||
else # NS_USE_GCC
|
||||
# FPU_TARGET_OPTIMIZER specifies the target processor and cache
|
||||
# properties of the ABI32_FPU and ABI64_FPU architectures for use
|
||||
# by the optimizer.
|
||||
ifeq (,$(findstring Sun WorkShop 6,$(shell $(CC) -V 2>&1)))
|
||||
# if the compiler is not Forte 6
|
||||
FPU_TARGET_OPTIMIZER = -xcache=64/32/4:1024/64/4 -xchip=ultra3
|
||||
else
|
||||
# Forte 6 C compiler generates incorrect code for rijndael.c
|
||||
# if -xchip=ultra3 is used (Bugzilla bug 333925). So we revert
|
||||
# to what we used in NSS 3.10.
|
||||
FPU_TARGET_OPTIMIZER = -xchip=ultra2
|
||||
endif
|
||||
ifdef USE_ABI32_INT32
|
||||
#ARCHFLAG=-xarch=v8 set in coreconf/sunOS5.mk
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
# 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
|
||||
# with SunStudio 10.
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -xO4
|
||||
endif
|
||||
SOL_CFLAGS += -xtarget=generic
|
||||
ARCHFLAG = -xarch=v8plus
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
# 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
|
||||
SOL_CFLAGS += -fsingle -xmemalign=8s
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
|
||||
SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
|
||||
SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
|
||||
SOL_CFLAGS += -xlibmil -xO5
|
||||
endif
|
||||
ARCHFLAG = -xarch=v8plusa
|
||||
SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture,
|
||||
# no FPU (non-VIS cpus). For building with SunStudio 10.
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -xO4
|
||||
endif
|
||||
SOL_CFLAGS += -xtarget=generic
|
||||
ARCHFLAG = -xarch=v9
|
||||
SOLARIS_AS_FLAGS = -xarch=v9 -K PIC
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size.
|
||||
# See comment for USE_ABI32_FPU.
|
||||
SOL_CFLAGS += -fsingle -xmemalign=8s
|
||||
ifdef BUILD_OPT
|
||||
SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fsimple=1
|
||||
SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all
|
||||
SOL_CFLAGS += $(FPU_TARGET_OPTIMIZER) -xdepend
|
||||
SOL_CFLAGS += -xlibmil -xO5
|
||||
endif
|
||||
ARCHFLAG = -xarch=v9a
|
||||
SOLARIS_AS_FLAGS = -xarch=v9a -K PIC
|
||||
endif
|
||||
endif # NS_USE_GCC
|
||||
|
||||
### set flags for both GCC and Sun cc
|
||||
ifdef USE_ABI32_INT32
|
||||
# this builds for Sparc v8 pure 32-bit architecture
|
||||
DEFINES += -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
ASFILES = mpv_sparcv8x.s
|
||||
DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
# 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,
|
||||
# 32-bit ABI, it uses FPU code, and 32-bit word size
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv8.s montmulfv8.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
|
||||
ECL_USE_FP = 1
|
||||
endif
|
||||
ifdef USE_ABI64_INT
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# best times are with no MP_ flags specified
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
# this builds for Sparc v9a pure 64-bit architecture
|
||||
# It uses floating point, and 32-bit word size
|
||||
MPI_SRCS += mpi_sparc.c
|
||||
ASFILES = mpv_sparcv9.s montmulfv9.s
|
||||
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
|
||||
ECL_USE_FP = 1
|
||||
endif
|
||||
|
||||
else
|
||||
# Solaris for non-sparc family CPUs
|
||||
ifdef NS_USE_GCC
|
||||
LD = gcc
|
||||
AS = gcc
|
||||
ASFLAGS =
|
||||
endif
|
||||
ifeq ($(USE_64),1)
|
||||
# Solaris for AMD64
|
||||
ifdef NS_USE_GCC
|
||||
ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s
|
||||
ASFLAGS += -march=opteron -m64 -fPIC
|
||||
MPI_SRCS += mp_comba.c
|
||||
else
|
||||
ASFILES = arcfour-amd64-sun.s mpi_amd64_sun.s sha-fast-amd64-sun.s
|
||||
ASFILES += mp_comba_amd64_sun.s mpcpucache_amd64.s
|
||||
ASFLAGS += -xarch=generic64 -K PIC
|
||||
SHA_SRCS =
|
||||
MPCPU_SRCS =
|
||||
endif
|
||||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
MPI_SRCS += mpi_amd64.c
|
||||
else
|
||||
# Solaris x86
|
||||
DEFINES += -D_X86_
|
||||
DEFINES += -DMP_USE_UINT_DIGIT
|
||||
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
|
||||
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D
|
||||
ASFILES = mpi_i86pc.s
|
||||
ifndef NS_USE_GCC
|
||||
MPCPU_SRCS =
|
||||
ASFILES += mpcpucache_x86.s
|
||||
endif
|
||||
endif
|
||||
endif # Solaris for non-sparc family CPUs
|
||||
endif # target == SunOS
|
||||
|
||||
ifdef NSS_ENABLE_ECC
|
||||
ifdef ECL_USE_FP
|
||||
#enable floating point ECC code
|
||||
DEFINES += -DECL_USE_FP
|
||||
ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
|
||||
ECL_HDRS += ecp_fp.h
|
||||
endif
|
||||
endif # NSS_ENABLE_ECC
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (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
|
||||
vpath %.c mpi ecl
|
||||
vpath %.S mpi ecl
|
||||
vpath %.s mpi ecl
|
||||
vpath %.asm mpi ecl
|
||||
INCLUDES += -Impi -Iecl
|
||||
|
||||
|
||||
DEFINES += -DMP_API_COMPATIBLE
|
||||
|
||||
MPI_USERS = 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)))
|
||||
|
||||
$(MPI_OBJS): $(MPI_HDRS)
|
||||
|
||||
ECL_USERS = ec.c
|
||||
|
||||
ECL_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_SRCS:.c=$(OBJ_SUFFIX)) $(ECL_ASM_SRCS:$(ASM_SUFFIX)=$(OBJ_SUFFIX)))
|
||||
ECL_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_USERS:.c=$(OBJ_SUFFIX)))
|
||||
|
||||
$(ECL_OBJS): $(ECL_HDRS)
|
||||
|
||||
|
||||
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
|
||||
|
||||
$(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)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpv_sparcv9.o $(OBJDIR)/montmulfv9.o : $(OBJDIR)/%.o : %.s
|
||||
@$(MAKE_OBJDIR)
|
||||
$(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $<
|
||||
|
||||
$(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h
|
||||
|
||||
endif
|
||||
|
||||
ifndef FREEBL_CHILD_BUILD
|
||||
|
||||
# Parent build. This is where we decide which shared libraries to build
|
||||
|
||||
ifdef FREEBL_BUILD_SINGLE_SHLIB
|
||||
|
||||
################### Single shared lib stuff #########################
|
||||
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 \
|
||||
OBJDIR=$(SINGLE_SHLIB_DIR) $@
|
||||
######################## common stuff #########################
|
||||
|
||||
endif
|
||||
|
||||
# multiple shared libraries
|
||||
|
||||
######################## ABI32_FPU stuff #########################
|
||||
ifdef HAVE_ABI32_FPU
|
||||
ABI32_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_FPU
|
||||
ALL_TRASH += $(ABI32_FPU_DIR)
|
||||
|
||||
$(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
|
||||
|
||||
endif # FREEBL_CHILD_BUILD
|
||||
|
||||
|
||||
# Bugzilla Bug 333917: the non-x86 code in desblapi.c seems to violate
|
||||
# ANSI C's strict aliasing rules.
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
ifneq ($(CPU_ARCH),x86)
|
||||
$(OBJDIR)/$(PROG_PREFIX)desblapi$(OBJ_SUFFIX): desblapi.c
|
||||
@$(MAKE_OBJDIR)
|
||||
ifdef NEED_ABSOLUTE_PATH
|
||||
$(CC) -o $@ -c $(CFLAGS) -fno-strict-aliasing $(call core_abspath,$<)
|
||||
else
|
||||
$(CC) -o $@ -c $(CFLAGS) -fno-strict-aliasing $<
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,413 +0,0 @@
|
||||
/*
|
||||
* aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: aeskeywrap.c,v 1.4 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
|
||||
|
||||
/* $Id: aeskeywrap.c,v 1.4 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
|
||||
|
||||
#include "prcpucfg.h"
|
||||
#if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
|
||||
#else
|
||||
#define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
|
||||
#endif
|
||||
#include "prtypes.h" /* for PRUintXX */
|
||||
#include "secport.h" /* for PORT_XXX */
|
||||
#include "secerr.h"
|
||||
#include "blapi.h" /* for AES_ functions */
|
||||
#include "rijndael.h"
|
||||
|
||||
struct AESKeyWrapContextStr {
|
||||
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
|
||||
AESContext aescx;
|
||||
};
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** AES key wrap algorithm, RFC 3394
|
||||
*/
|
||||
|
||||
AESKeyWrapContext *
|
||||
AESKeyWrap_AllocateContext(void)
|
||||
{
|
||||
AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
|
||||
return cx;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
AESKeyWrap_InitContext(AESKeyWrapContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int x1,
|
||||
unsigned int encrypt,
|
||||
unsigned int x2)
|
||||
{
|
||||
SECStatus rv = SECFailure;
|
||||
if (!cx) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (iv) {
|
||||
memcpy(cx->iv, iv, sizeof cx->iv);
|
||||
} else {
|
||||
memset(cx->iv, 0xA6, sizeof cx->iv);
|
||||
}
|
||||
rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
|
||||
AES_BLOCK_SIZE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new AES context suitable for AES encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "keylen" the number of bytes of key data (16, 24, or 32)
|
||||
*/
|
||||
extern AESKeyWrapContext *
|
||||
AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
|
||||
int encrypt, unsigned int keylen)
|
||||
{
|
||||
SECStatus rv;
|
||||
AESKeyWrapContext * cx = AESKeyWrap_AllocateContext();
|
||||
if (!cx)
|
||||
return NULL; /* error is already set */
|
||||
rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Free(cx);
|
||||
cx = NULL; /* error should already be set */
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy a AES KeyWrap context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
extern void
|
||||
AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
AES_DestroyContext(&cx->aescx, PR_FALSE);
|
||||
/* memset(cx, 0, sizeof *cx); */
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
|
||||
/* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
|
||||
** (Most significant byte first) in memory. The only ALU operations done
|
||||
** on them are increment, decrement, and XOR. So, on little-endian CPUs,
|
||||
** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
|
||||
** are simulated in the following code. This is thought to be faster and
|
||||
** simpler than trying to convert the data to little-endian and back.
|
||||
*/
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function increments the 64-bit value T, and then
|
||||
** XORs it with A, changing A.
|
||||
*/
|
||||
static void
|
||||
increment_and_xor(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
if (!++T[7])
|
||||
if (!++T[6])
|
||||
if (!++T[5])
|
||||
if (!++T[4])
|
||||
if (!++T[3])
|
||||
if (!++T[2])
|
||||
if (!++T[1])
|
||||
++T[0];
|
||||
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
}
|
||||
|
||||
/* A and T point to two 64-bit values stored most signficant byte first
|
||||
** (big endian). This function XORs T with A, giving a new A, then
|
||||
** decrements the 64-bit value T.
|
||||
*/
|
||||
static void
|
||||
xor_and_decrement(unsigned char *A, unsigned char *T)
|
||||
{
|
||||
A[0] ^= T[0];
|
||||
A[1] ^= T[1];
|
||||
A[2] ^= T[2];
|
||||
A[3] ^= T[3];
|
||||
A[4] ^= T[4];
|
||||
A[5] ^= T[5];
|
||||
A[6] ^= T[6];
|
||||
A[7] ^= T[7];
|
||||
|
||||
if (!T[7]--)
|
||||
if (!T[6]--)
|
||||
if (!T[5]--)
|
||||
if (!T[4]--)
|
||||
if (!T[3]--)
|
||||
if (!T[2]--)
|
||||
if (!T[1]--)
|
||||
T[0]--;
|
||||
|
||||
}
|
||||
|
||||
/* Given an unsigned long t (in host byte order), store this value as a
|
||||
** 64-bit big-endian value (MSB first) in *pt.
|
||||
*/
|
||||
static void
|
||||
set_t(unsigned char *pt, unsigned long t)
|
||||
{
|
||||
pt[7] = (unsigned char)t; t >>= 8;
|
||||
pt[6] = (unsigned char)t; t >>= 8;
|
||||
pt[5] = (unsigned char)t; t >>= 8;
|
||||
pt[4] = (unsigned char)t; t >>= 8;
|
||||
pt[3] = (unsigned char)t; t >>= 8;
|
||||
pt[2] = (unsigned char)t; t >>= 8;
|
||||
pt[1] = (unsigned char)t; t >>= 8;
|
||||
pt[0] = (unsigned char)t;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Perform AES 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_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks + 1);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
memcpy(&R[1], input, inputLen);
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 0;
|
||||
#else
|
||||
memset(&t, 0, sizeof t);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = 1; i <= nBlocks; ++i) {
|
||||
B[1] = R[i];
|
||||
s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
/* here, increment t and XOR A with t (in big endian order); */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= ++t;
|
||||
#else
|
||||
increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
R[0] = A;
|
||||
memcpy(output, &R[0], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, outLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
|
||||
/*
|
||||
** Perform AES 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_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
|
||||
unsigned int *pOutputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint64 * R = NULL;
|
||||
unsigned int nBlocks;
|
||||
unsigned int i, j;
|
||||
unsigned int aesLen = AES_BLOCK_SIZE;
|
||||
unsigned int outLen;
|
||||
SECStatus s = SECFailure;
|
||||
/* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
|
||||
PRUint64 t;
|
||||
PRUint64 B[2];
|
||||
|
||||
#define A B[0]
|
||||
|
||||
/* Check args */
|
||||
if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
|
||||
0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
|
||||
#ifdef maybe
|
||||
if (!output && pOutputLen) { /* caller is asking for output size */
|
||||
*pOutputLen = outLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
if (maxOutputLen < outLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return s;
|
||||
}
|
||||
if (cx == NULL || output == NULL || input == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return s;
|
||||
}
|
||||
nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
|
||||
R = PORT_NewArray(PRUint64, nBlocks);
|
||||
if (!R)
|
||||
return s; /* error is already set. */
|
||||
nBlocks--;
|
||||
/*
|
||||
** 1) Initialize variables.
|
||||
*/
|
||||
memcpy(&R[0], input, inputLen);
|
||||
A = R[0];
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
t = 6UL * nBlocks;
|
||||
#else
|
||||
set_t((unsigned char *)&t, 6UL * nBlocks);
|
||||
#endif
|
||||
/*
|
||||
** 2) Calculate intermediate values.
|
||||
*/
|
||||
for (j = 0; j < 6; ++j) {
|
||||
for (i = nBlocks; i; --i) {
|
||||
/* here, XOR A with t (in big endian order) and decrement t; */
|
||||
#if BIG_ENDIAN_WITH_64_BIT_REGISTERS
|
||||
A ^= t--;
|
||||
#else
|
||||
xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
|
||||
#endif
|
||||
B[1] = R[i];
|
||||
s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
|
||||
sizeof B, (unsigned char *)B, sizeof B);
|
||||
if (s != SECSuccess)
|
||||
break;
|
||||
R[i] = B[1];
|
||||
}
|
||||
}
|
||||
/*
|
||||
** 3) Output the results.
|
||||
*/
|
||||
if (s == SECSuccess) {
|
||||
int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
|
||||
if (!bad) {
|
||||
memcpy(output, &R[1], outLen);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = outLen;
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
if (pOutputLen)
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
} else if (pOutputLen) {
|
||||
*pOutputLen = 0;
|
||||
}
|
||||
PORT_ZFree(R, inputLen);
|
||||
return s;
|
||||
}
|
||||
#undef A
|
||||
@@ -1,515 +0,0 @@
|
||||
/*
|
||||
* alg2268.c - implementation of the algorithm in RFC 2268
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* $Id: alg2268.c,v 1.7 2005-08-06 07:24:21 nelsonb%netscape.com Exp $ */
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
#ifdef XP_UNIX_XXX
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** RC2 symmetric block cypher
|
||||
*/
|
||||
|
||||
typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* forward declarations */
|
||||
static rc2Func rc2_EncryptECB;
|
||||
static rc2Func rc2_DecryptECB;
|
||||
static rc2Func rc2_EncryptCBC;
|
||||
static rc2Func rc2_DecryptCBC;
|
||||
|
||||
typedef union {
|
||||
PRUint32 l[2];
|
||||
PRUint16 s[4];
|
||||
PRUint8 b[8];
|
||||
} RC2Block;
|
||||
|
||||
struct RC2ContextStr {
|
||||
union {
|
||||
PRUint8 Kb[128];
|
||||
PRUint16 Kw[64];
|
||||
} u;
|
||||
RC2Block iv;
|
||||
rc2Func *enc;
|
||||
rc2Func *dec;
|
||||
};
|
||||
|
||||
#define B u.Kb
|
||||
#define K u.Kw
|
||||
#define BYTESWAP(x) ((x) << 8 | (x) >> 8)
|
||||
#define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS))
|
||||
#define RC2_BLOCK_SIZE 8
|
||||
|
||||
#define LOAD_HARD(R) \
|
||||
R[0] = (PRUint16)input[1] << 8 | input[0]; \
|
||||
R[1] = (PRUint16)input[3] << 8 | input[2]; \
|
||||
R[2] = (PRUint16)input[5] << 8 | input[4]; \
|
||||
R[3] = (PRUint16)input[7] << 8 | input[6];
|
||||
#define LOAD_EASY(R) \
|
||||
R[0] = ((PRUint16 *)input)[0]; \
|
||||
R[1] = ((PRUint16 *)input)[1]; \
|
||||
R[2] = ((PRUint16 *)input)[2]; \
|
||||
R[3] = ((PRUint16 *)input)[3];
|
||||
#define STORE_HARD(R) \
|
||||
output[0] = (PRUint8)(R[0]); output[1] = (PRUint8)(R[0] >> 8); \
|
||||
output[2] = (PRUint8)(R[1]); output[3] = (PRUint8)(R[1] >> 8); \
|
||||
output[4] = (PRUint8)(R[2]); output[5] = (PRUint8)(R[2] >> 8); \
|
||||
output[6] = (PRUint8)(R[3]); output[7] = (PRUint8)(R[3] >> 8);
|
||||
#define STORE_EASY(R) \
|
||||
((PRUint16 *)output)[0] = R[0]; \
|
||||
((PRUint16 *)output)[1] = R[1]; \
|
||||
((PRUint16 *)output)[2] = R[2]; \
|
||||
((PRUint16 *)output)[3] = R[3];
|
||||
|
||||
#if defined (_X86_)
|
||||
#define LOAD(R) LOAD_EASY(R)
|
||||
#define STORE(R) STORE_EASY(R)
|
||||
#elif !defined(IS_LITTLE_ENDIAN)
|
||||
#define LOAD(R) LOAD_HARD(R)
|
||||
#define STORE(R) STORE_HARD(R)
|
||||
#else
|
||||
#define LOAD(R) if ((ptrdiff_t)input & 1) { LOAD_HARD(R) } else { LOAD_EASY(R) }
|
||||
#define STORE(R) if ((ptrdiff_t)input & 1) { STORE_HARD(R) } else { STORE_EASY(R) }
|
||||
#endif
|
||||
|
||||
static const PRUint8 S[256] = {
|
||||
0331,0170,0371,0304,0031,0335,0265,0355,0050,0351,0375,0171,0112,0240,0330,0235,
|
||||
0306,0176,0067,0203,0053,0166,0123,0216,0142,0114,0144,0210,0104,0213,0373,0242,
|
||||
0027,0232,0131,0365,0207,0263,0117,0023,0141,0105,0155,0215,0011,0201,0175,0062,
|
||||
0275,0217,0100,0353,0206,0267,0173,0013,0360,0225,0041,0042,0134,0153,0116,0202,
|
||||
0124,0326,0145,0223,0316,0140,0262,0034,0163,0126,0300,0024,0247,0214,0361,0334,
|
||||
0022,0165,0312,0037,0073,0276,0344,0321,0102,0075,0324,0060,0243,0074,0266,0046,
|
||||
0157,0277,0016,0332,0106,0151,0007,0127,0047,0362,0035,0233,0274,0224,0103,0003,
|
||||
0370,0021,0307,0366,0220,0357,0076,0347,0006,0303,0325,0057,0310,0146,0036,0327,
|
||||
0010,0350,0352,0336,0200,0122,0356,0367,0204,0252,0162,0254,0065,0115,0152,0052,
|
||||
0226,0032,0322,0161,0132,0025,0111,0164,0113,0237,0320,0136,0004,0030,0244,0354,
|
||||
0302,0340,0101,0156,0017,0121,0313,0314,0044,0221,0257,0120,0241,0364,0160,0071,
|
||||
0231,0174,0072,0205,0043,0270,0264,0172,0374,0002,0066,0133,0045,0125,0227,0061,
|
||||
0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311,
|
||||
0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251,
|
||||
0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056,
|
||||
0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255
|
||||
};
|
||||
|
||||
RC2Context * RC2_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(RC2Context);
|
||||
}
|
||||
SECStatus
|
||||
RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len,
|
||||
const unsigned char *input, int mode, unsigned int efLen8,
|
||||
unsigned int unused)
|
||||
{
|
||||
PRUint8 *L,*L2;
|
||||
int i;
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
PRUint16 tmpS;
|
||||
#endif
|
||||
PRUint8 tmpB;
|
||||
|
||||
if (!key || !cx || !len || len > (sizeof cx->B) ||
|
||||
efLen8 > (sizeof cx->B)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (mode == NSS_RC2) {
|
||||
/* groovy */
|
||||
} else if (mode == NSS_RC2_CBC) {
|
||||
if (!input) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (mode == NSS_RC2_CBC) {
|
||||
cx->enc = & rc2_EncryptCBC;
|
||||
cx->dec = & rc2_DecryptCBC;
|
||||
LOAD(cx->iv.s);
|
||||
} else {
|
||||
cx->enc = & rc2_EncryptECB;
|
||||
cx->dec = & rc2_DecryptECB;
|
||||
}
|
||||
|
||||
/* Step 0. Copy key into table. */
|
||||
memcpy(cx->B, key, len);
|
||||
|
||||
/* Step 1. Compute all values to the right of the key. */
|
||||
L2 = cx->B;
|
||||
L = L2 + len;
|
||||
tmpB = L[-1];
|
||||
for (i = (sizeof cx->B) - len; i > 0; --i) {
|
||||
*L++ = tmpB = S[ (PRUint8)(tmpB + *L2++) ];
|
||||
}
|
||||
|
||||
/* step 2. Adjust left most byte of effective key. */
|
||||
i = (sizeof cx->B) - efLen8;
|
||||
L = cx->B + i;
|
||||
*L = tmpB = S[*L]; /* mask is always 0xff */
|
||||
|
||||
/* step 3. Recompute all values to the left of effective key. */
|
||||
L2 = --L + efLen8;
|
||||
while(L >= cx->B) {
|
||||
*L-- = tmpB = S[ tmpB ^ *L2-- ];
|
||||
}
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
for (i = 63; i >= 0; --i) {
|
||||
SWAPK(i); /* candidate for unrolling */
|
||||
}
|
||||
#endif
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new RC2 context suitable for RC2 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC)
|
||||
** "mode" one of NSS_RC2 or NSS_RC2_CBC
|
||||
** "effectiveKeyLen" in bytes, not bits.
|
||||
**
|
||||
** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC2Context *
|
||||
RC2_CreateContext(const unsigned char *key, unsigned int len,
|
||||
const unsigned char *iv, int mode, unsigned efLen8)
|
||||
{
|
||||
RC2Context *cx = PORT_ZNew(RC2Context);
|
||||
if (cx) {
|
||||
SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0);
|
||||
if (rv != SECSuccess) {
|
||||
RC2_DestroyContext(cx, PR_TRUE);
|
||||
cx = NULL;
|
||||
}
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC2 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC2_DestroyContext(RC2Context *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit) {
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ROL(x,k) (x << k | x >> (16-k))
|
||||
#define MIX(j) \
|
||||
R0 = R0 + cx->K[ 4*j+0] + (R3 & R2) + (~R3 & R1); R0 = ROL(R0,1);\
|
||||
R1 = R1 + cx->K[ 4*j+1] + (R0 & R3) + (~R0 & R2); R1 = ROL(R1,2);\
|
||||
R2 = R2 + cx->K[ 4*j+2] + (R1 & R0) + (~R1 & R3); R2 = ROL(R2,3);\
|
||||
R3 = R3 + cx->K[ 4*j+3] + (R2 & R1) + (~R2 & R0); R3 = ROL(R3,5)
|
||||
#define MASH \
|
||||
R0 = R0 + cx->K[R3 & 63];\
|
||||
R1 = R1 + cx->K[R0 & 63];\
|
||||
R2 = R2 + cx->K[R1 & 63];\
|
||||
R3 = R3 + cx->K[R2 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 0 */
|
||||
/* step 4. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(0);
|
||||
MIX(1);
|
||||
MIX(2);
|
||||
MIX(3);
|
||||
MIX(4);
|
||||
|
||||
/* step 5. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 6. Perform 6 mixing rounds. */
|
||||
|
||||
MIX(5);
|
||||
MIX(6);
|
||||
MIX(7);
|
||||
MIX(8);
|
||||
MIX(9);
|
||||
MIX(10);
|
||||
|
||||
/* step 7. Perform 1 mashing round. */
|
||||
MASH;
|
||||
|
||||
/* step 8. Perform 5 mixing rounds. */
|
||||
|
||||
MIX(11);
|
||||
MIX(12);
|
||||
MIX(13);
|
||||
MIX(14);
|
||||
MIX(15);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
#define ROR(x,k) (x >> k | x << (16-k))
|
||||
#define R_MIX(j) \
|
||||
R3 = ROR(R3,5); R3 = R3 - cx->K[ 4*j+3] - (R2 & R1) - (~R2 & R0); \
|
||||
R2 = ROR(R2,3); R2 = R2 - cx->K[ 4*j+2] - (R1 & R0) - (~R1 & R3); \
|
||||
R1 = ROR(R1,2); R1 = R1 - cx->K[ 4*j+1] - (R0 & R3) - (~R0 & R2); \
|
||||
R0 = ROR(R0,1); R0 = R0 - cx->K[ 4*j+0] - (R3 & R2) - (~R3 & R1)
|
||||
#define R_MASH \
|
||||
R3 = R3 - cx->K[R2 & 63];\
|
||||
R2 = R2 - cx->K[R1 & 63];\
|
||||
R1 = R1 - cx->K[R0 & 63];\
|
||||
R0 = R0 - cx->K[R3 & 63]
|
||||
|
||||
/* Encrypt one block */
|
||||
static void
|
||||
rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
|
||||
{
|
||||
register PRUint16 R0, R1, R2, R3;
|
||||
|
||||
/* step 1. Initialize input. */
|
||||
R0 = input->s[0];
|
||||
R1 = input->s[1];
|
||||
R2 = input->s[2];
|
||||
R3 = input->s[3];
|
||||
|
||||
/* step 2. Expand Key (already done, in context) */
|
||||
/* step 3. j = 63 */
|
||||
/* step 4. Perform 5 r_mixing rounds. */
|
||||
R_MIX(15);
|
||||
R_MIX(14);
|
||||
R_MIX(13);
|
||||
R_MIX(12);
|
||||
R_MIX(11);
|
||||
|
||||
/* step 5. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 6. Perform 6 r_mixing rounds. */
|
||||
R_MIX(10);
|
||||
R_MIX(9);
|
||||
R_MIX(8);
|
||||
R_MIX(7);
|
||||
R_MIX(6);
|
||||
R_MIX(5);
|
||||
|
||||
/* step 7. Perform 1 r_mashing round. */
|
||||
R_MASH;
|
||||
|
||||
/* step 8. Perform 5 r_mixing rounds. */
|
||||
R_MIX(4);
|
||||
R_MIX(3);
|
||||
R_MIX(2);
|
||||
R_MIX(1);
|
||||
R_MIX(0);
|
||||
|
||||
/* output results */
|
||||
output->s[0] = R0;
|
||||
output->s[1] = R1;
|
||||
output->s[2] = R2;
|
||||
output->s[3] = R3;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptECB(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &iBlock, &iBlock);
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_EncryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
|
||||
LOAD(iBlock.s)
|
||||
iBlock.l[0] ^= cx->iv.l[0];
|
||||
iBlock.l[1] ^= cx->iv.l[1];
|
||||
rc2_Encrypt1Block(cx, &iBlock, &iBlock);
|
||||
cx->iv = iBlock;
|
||||
STORE(iBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
rc2_DecryptCBC(RC2Context *cx, unsigned char *output,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
RC2Block iBlock;
|
||||
RC2Block oBlock;
|
||||
|
||||
while (inputLen > 0) {
|
||||
LOAD(iBlock.s)
|
||||
rc2_Decrypt1Block(cx, &oBlock, &iBlock);
|
||||
oBlock.l[0] ^= cx->iv.l[0];
|
||||
oBlock.l[1] ^= cx->iv.l[1];
|
||||
cx->iv = iBlock;
|
||||
STORE(oBlock.s)
|
||||
output += RC2_BLOCK_SIZE;
|
||||
input += RC2_BLOCK_SIZE;
|
||||
inputLen -= RC2_BLOCK_SIZE;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Perform RC2 encryption.
|
||||
** "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
|
||||
*/
|
||||
SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->enc)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC2 decryption.
|
||||
** "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
|
||||
*/
|
||||
SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
if (inputLen) {
|
||||
if (inputLen % RC2_BLOCK_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = (*cx->dec)(cx, output, input, inputLen);
|
||||
}
|
||||
if (rv == SECSuccess) {
|
||||
*outputLen = inputLen;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "secport.h"
|
||||
#include "hasht.h"
|
||||
#include "blapit.h"
|
||||
#include "alghmac.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#define HMAC_PAD_SIZE HASH_BLOCK_LENGTH_MAX
|
||||
|
||||
struct HMACContextStr {
|
||||
void *hash;
|
||||
const SECHashObject *hashobj;
|
||||
PRBool wasAllocated;
|
||||
unsigned char ipad[HMAC_PAD_SIZE];
|
||||
unsigned char opad[HMAC_PAD_SIZE];
|
||||
};
|
||||
|
||||
void
|
||||
HMAC_Destroy(HMACContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx == NULL)
|
||||
return;
|
||||
|
||||
PORT_Assert(!freeit == !cx->wasAllocated);
|
||||
if (cx->hash != NULL) {
|
||||
cx->hashobj->destroy(cx->hash, PR_TRUE);
|
||||
PORT_Memset(cx, 0, sizeof *cx);
|
||||
}
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
HMAC_Init( HMACContext * cx, const SECHashObject *hash_obj,
|
||||
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) {
|
||||
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);
|
||||
cx->hashobj->update(cx->hash, secret, secret_len);
|
||||
PORT_Assert(cx->hashobj->length <= sizeof hashed_secret);
|
||||
cx->hashobj->end( cx->hash, hashed_secret, &secret_len,
|
||||
sizeof hashed_secret);
|
||||
if (secret_len != cx->hashobj->length) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser;
|
||||
}
|
||||
secret = (const unsigned char *)&hashed_secret[0];
|
||||
}
|
||||
|
||||
PORT_Memset(cx->ipad, 0x36, cx->hashobj->blocklength);
|
||||
PORT_Memset(cx->opad, 0x5c, cx->hashobj->blocklength);
|
||||
|
||||
/* fold secret into padding */
|
||||
for (i = 0; i < secret_len; i++) {
|
||||
cx->ipad[i] ^= secret[i];
|
||||
cx->opad[i] ^= secret[i];
|
||||
}
|
||||
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
PORT_Memset(hashed_secret, 0, sizeof hashed_secret);
|
||||
if (cx->hash != NULL)
|
||||
cx->hashobj->destroy(cx->hash, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
HMACContext *
|
||||
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS)
|
||||
{
|
||||
SECStatus rv;
|
||||
HMACContext * cx = PORT_ZNew(HMACContext);
|
||||
if (cx == NULL)
|
||||
return NULL;
|
||||
rv = HMAC_Init(cx, hash_obj, secret, secret_len, isFIPS);
|
||||
cx->wasAllocated = PR_TRUE;
|
||||
if (rv != SECSuccess) {
|
||||
PORT_Free(cx); /* contains no secret info */
|
||||
cx = NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
HMAC_Begin(HMACContext *cx)
|
||||
{
|
||||
/* start inner hash */
|
||||
cx->hashobj->begin(cx->hash);
|
||||
cx->hashobj->update(cx->hash, cx->ipad, cx->hashobj->blocklength);
|
||||
}
|
||||
|
||||
void
|
||||
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len)
|
||||
{
|
||||
cx->hashobj->update(cx->hash, data, data_len);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len)
|
||||
{
|
||||
if (max_result_len < cx->hashobj->length) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
|
||||
if (*result_len != cx->hashobj->length)
|
||||
return SECFailure;
|
||||
|
||||
cx->hashobj->begin(cx->hash);
|
||||
cx->hashobj->update(cx->hash, cx->opad, cx->hashobj->blocklength);
|
||||
cx->hashobj->update(cx->hash, result, *result_len);
|
||||
cx->hashobj->end(cx->hash, result, result_len, max_result_len);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
HMACContext *
|
||||
HMAC_Clone(HMACContext *cx)
|
||||
{
|
||||
HMACContext *newcx;
|
||||
|
||||
newcx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext));
|
||||
if (newcx == NULL)
|
||||
goto loser;
|
||||
|
||||
newcx->wasAllocated = PR_TRUE;
|
||||
newcx->hashobj = cx->hashobj;
|
||||
newcx->hash = cx->hashobj->clone(cx->hash);
|
||||
if (newcx->hash == NULL)
|
||||
goto loser;
|
||||
PORT_Memcpy(newcx->ipad, cx->ipad, cx->hashobj->blocklength);
|
||||
PORT_Memcpy(newcx->opad, cx->opad, cx->hashobj->blocklength);
|
||||
return newcx;
|
||||
|
||||
loser:
|
||||
HMAC_Destroy(newcx, PR_TRUE);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _ALGHMAC_H_
|
||||
#define _ALGHMAC_H_
|
||||
|
||||
typedef struct HMACContextStr HMACContext;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
/* destroy HMAC context */
|
||||
extern void
|
||||
HMAC_Destroy(HMACContext *cx, PRBool freeit);
|
||||
|
||||
/* create HMAC context
|
||||
* hash_obj hash object from SECRawHashObjects[]
|
||||
* secret the secret with which the HMAC is performed.
|
||||
* secret_len the length of the secret.
|
||||
* isFIPS true if conforming to FIPS 198.
|
||||
*
|
||||
* NULL is returned if an error occurs.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS);
|
||||
|
||||
/* like HMAC_Create, except caller allocates HMACContext. */
|
||||
SECStatus
|
||||
HMAC_Init(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);
|
||||
|
||||
/* update HMAC
|
||||
* cx HMAC Context
|
||||
* data the data to perform HMAC on
|
||||
* data_len the length of the data to process
|
||||
*/
|
||||
extern void
|
||||
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len);
|
||||
|
||||
/* Finish HMAC -- place the results within result
|
||||
* cx HMAC context
|
||||
* result buffer for resulting hmac'd data
|
||||
* result_len where the resultant hmac length is stored
|
||||
* max_result_len maximum possible length that can be stored in result
|
||||
*/
|
||||
extern SECStatus
|
||||
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
|
||||
unsigned int max_result_len);
|
||||
|
||||
/* clone a copy of the HMAC state. this is usefult when you would
|
||||
* need to keep a running hmac but also need to extract portions
|
||||
* partway through the process.
|
||||
*/
|
||||
extern HMACContext *
|
||||
HMAC_Clone(HMACContext *cx);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* arcfive.c - stubs for RC5 - NOT a working implementation!
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: arcfive.c,v 1.5 2004-04-27 23:04:36 gerv%gerv.net Exp $ */
|
||||
|
||||
#include "blapi.h"
|
||||
#include "prerror.h"
|
||||
|
||||
/******************************************/
|
||||
/*
|
||||
** RC5 symmetric block cypher -- 64-bit block size
|
||||
*/
|
||||
|
||||
/*
|
||||
** Create a new RC5 context suitable for RC5 encryption/decryption.
|
||||
** "key" raw key data
|
||||
** "len" the number of bytes of key data
|
||||
** "iv" is the CBC initialization vector (if mode is NSS_RC5_CBC)
|
||||
** "mode" one of NSS_RC5 or NSS_RC5_CBC
|
||||
**
|
||||
** When mode is set to NSS_RC5_CBC the RC5 cipher is run in "cipher block
|
||||
** chaining" mode.
|
||||
*/
|
||||
RC5Context *
|
||||
RC5_CreateContext(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destroy an RC5 encryption/decryption context.
|
||||
** "cx" the context
|
||||
** "freeit" if PR_TRUE then free the object as well as its sub-objects
|
||||
*/
|
||||
void
|
||||
RC5_DestroyContext(RC5Context *cx, PRBool freeit)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 encryption.
|
||||
** "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
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Encrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
** Perform RC5 decryption.
|
||||
** "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
|
||||
*/
|
||||
SECStatus
|
||||
RC5_Decrypt(RC5Context *cx, unsigned char *output, unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Marc Bevand <bevand_m@epita.fr> .
|
||||
# Portions created by the Initial Developer are
|
||||
# Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# ** ARCFOUR implementation optimized for AMD64.
|
||||
# **
|
||||
# ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
# ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp # key = ARG(key)
|
||||
movq %rsi, %rbx # rbx = ARG(len)
|
||||
movq %rdx, %rsi # in = ARG(in)
|
||||
movq %rcx, %rdi # out = ARG(out)
|
||||
movq (%rbp), %rcx # x = key->x
|
||||
movq 8(%rbp), %rdx # y = key->y
|
||||
addq $16, %rbp # d = key->data
|
||||
incq %rcx # x++
|
||||
andq $255, %rcx # x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx # rbx = in+len-8
|
||||
movq %rbx, %r9 # tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax # tx = d[x]
|
||||
cmpq %rsi, %rbx # cmp in with in+len-8
|
||||
jl .Lend # jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi # increment in
|
||||
addq $8, %rdi # increment out
|
||||
|
||||
# generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 # byte counter
|
||||
1: addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 # (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
# xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi # cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart # jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 # tmp = in+len
|
||||
|
||||
# handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 # cmp in with in+len
|
||||
jle .Lfinished # jump if (in+len <= in)
|
||||
addb %al, %dl # y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx # ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) # d[x] = ty
|
||||
addb %al, %bl # val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) # d[y] = tx
|
||||
incb %cl # x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax # tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b # val = d[val]
|
||||
xorb (%rsi), %r8b # xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi # in++
|
||||
incq %rdi # out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx # x--
|
||||
movb %dl, -8(%rbp) # key->y = y
|
||||
movb %cl, -16(%rbp) # key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
|
||||
# Magic indicating no need for an executable stack
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.previous
|
||||
@@ -1,139 +0,0 @@
|
||||
; ***** BEGIN LICENSE BLOCK *****
|
||||
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;
|
||||
; The contents of this file are subject to the Mozilla Public License Version
|
||||
; 1.1 (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.mozilla.org/MPL/
|
||||
;
|
||||
; Software distributed under the License is distributed on an "AS IS" basis,
|
||||
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
; for the specific language governing rights and limitations under the
|
||||
; License.
|
||||
;
|
||||
; The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
;
|
||||
; The Initial Developer of the Original Code is
|
||||
; Marc Bevand <bevand_m@epita.fr> .
|
||||
; Portions created by the Initial Developer are
|
||||
; Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
;
|
||||
; Contributor(s):
|
||||
;
|
||||
; Alternatively, the contents of this file may be used under the terms of
|
||||
; either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
; in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
; of those above. If you wish to allow use of your version of this file only
|
||||
; under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
; use your version of this file under the terms of the MPL, indicate your
|
||||
; decision by deleting the provisions above and replace them with the notice
|
||||
; and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
; the provisions above, a recipient may use your version of this file under
|
||||
; the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;
|
||||
; ***** END LICENSE BLOCK *****
|
||||
|
||||
; ** ARCFOUR implementation optimized for AMD64.
|
||||
; **
|
||||
; ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
; ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.CODE
|
||||
|
||||
; extern void ARCFOUR(RC4Context *cx, unsigned long long inputLen,
|
||||
; const unsigned char *input, unsigned char *output);
|
||||
|
||||
|
||||
ARCFOUR PROC
|
||||
|
||||
push rbp
|
||||
push rbx
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
mov rbp, rcx ; key = ARG(key)
|
||||
mov rbx, rdx ; rbx = ARG(len)
|
||||
mov rsi, r8 ; in = ARG(in)
|
||||
mov rdi, r9 ; out = ARG(out)
|
||||
mov rcx, [rbp] ; x = key->x
|
||||
mov rdx, [rbp+8] ; y = key->y
|
||||
add rbp, 16 ; d = key->data
|
||||
inc rcx ; x++
|
||||
and rcx, 0ffh ; x &= 0xff
|
||||
lea rbx, [rbx+rsi-8] ; rbx = in+len-8
|
||||
mov r9, rbx ; tmp = in+len-8
|
||||
mov rax, [rbp+rcx*8] ; tx = d[x]
|
||||
cmp rbx, rsi ; cmp in with in+len-8
|
||||
jl Lend ; jump if (in+len-8 < in)
|
||||
|
||||
Lstart:
|
||||
add rsi, 8 ; increment in
|
||||
add rdi, 8 ; increment out
|
||||
|
||||
;
|
||||
; generate the next 8 bytes of the rc4 stream into r8
|
||||
;
|
||||
|
||||
mov r11, 8 ; byte counter
|
||||
|
||||
@@:
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
dec r11b
|
||||
ror r8, 8 ; (ror does not change ZF)
|
||||
jnz @b
|
||||
|
||||
;
|
||||
; xor 8 bytes
|
||||
;
|
||||
|
||||
xor r8, [rsi-8]
|
||||
cmp rsi, r9 ; cmp in+len-8 with in
|
||||
mov [rdi-8], r8
|
||||
jle Lstart
|
||||
|
||||
Lend:
|
||||
add r9, 8 ; tmp = in+len
|
||||
|
||||
;
|
||||
; handle the last bytes, one by one
|
||||
;
|
||||
|
||||
@@:
|
||||
cmp r9, rsi ; cmp in with in+len
|
||||
jle Lfinished ; jump if (in+len <= in)
|
||||
add dl, al ; y += tx
|
||||
mov ebx, [rbp+rdx*8] ; ty = d[y]
|
||||
mov [rbp+rcx*8], ebx ; d[x] = ty
|
||||
add bl, al ; val = ty + tx
|
||||
mov [rbp+rdx*8], eax ; d[y] = tx
|
||||
inc cl ; x++ (NEXT ROUND)
|
||||
mov eax, [rbp+rcx*8] ; tx = d[x] (NEXT ROUND)
|
||||
mov r8b, [rbp+rbx*8] ; val = d[val]
|
||||
xor r8b, [rsi] ; xor 1 byte
|
||||
mov [rdi], r8b
|
||||
inc rsi ; in++
|
||||
inc rdi
|
||||
jmp @b
|
||||
|
||||
Lfinished:
|
||||
dec rcx ; x--
|
||||
mov [rbp-8], dl ; key->y = y
|
||||
mov [rbp-16], cl ; key->x = x
|
||||
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
ARCFOUR ENDP
|
||||
|
||||
END
|
||||
@@ -1,116 +0,0 @@
|
||||
/ ***** BEGIN LICENSE BLOCK *****
|
||||
/ Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
/
|
||||
/ The contents of this file are subject to the Mozilla Public License Version
|
||||
/ 1.1 (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.mozilla.org/MPL/
|
||||
/
|
||||
/ Software distributed under the License is distributed on an "AS IS" basis,
|
||||
/ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
/ for the specific language governing rights and limitations under the
|
||||
/ License.
|
||||
/
|
||||
/ The Original Code is "Marc Bevand's fast AMD64 ARCFOUR source"
|
||||
/
|
||||
/ The Initial Developer of the Original Code is
|
||||
/ Marc Bevand <bevand_m@epita.fr> .
|
||||
/ Portions created by the Initial Developer are
|
||||
/ Copyright (C) 2004 the Initial Developer. All Rights Reserved.
|
||||
/
|
||||
/ Contributor(s):
|
||||
/
|
||||
/ Alternatively, the contents of this file may be used under the terms of
|
||||
/ either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
/ the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
/ in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
/ of those above. If you wish to allow use of your version of this file only
|
||||
/ under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
/ use your version of this file under the terms of the MPL, indicate your
|
||||
/ decision by deleting the provisions above and replace them with the notice
|
||||
/ and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
/ the provisions above, a recipient may use your version of this file under
|
||||
/ the terms of any one of the MPL, the GPL or the LGPL.
|
||||
/
|
||||
/ ***** END LICENSE BLOCK *****
|
||||
|
||||
/ ** ARCFOUR implementation optimized for AMD64.
|
||||
/ **
|
||||
/ ** The throughput achieved by this code is about 320 MBytes/sec, on
|
||||
/ ** a 1.8 GHz AMD Opteron (rev C0) processor.
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.globl ARCFOUR
|
||||
.type ARCFOUR,@function
|
||||
ARCFOUR:
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
movq %rdi, %rbp / key = ARG(key)
|
||||
movq %rsi, %rbx / rbx = ARG(len)
|
||||
movq %rdx, %rsi / in = ARG(in)
|
||||
movq %rcx, %rdi / out = ARG(out)
|
||||
movq (%rbp), %rcx / x = key->x
|
||||
movq 8(%rbp), %rdx / y = key->y
|
||||
addq $16, %rbp / d = key->data
|
||||
incq %rcx / x++
|
||||
andq $255, %rcx / x &= 0xff
|
||||
leaq -8(%rbx,%rsi), %rbx / rbx = in+len-8
|
||||
movq %rbx, %r9 / tmp = in+len-8
|
||||
movq 0(%rbp,%rcx,8), %rax / tx = d[x]
|
||||
cmpq %rsi, %rbx / cmp in with in+len-8
|
||||
jl .Lend / jump if (in+len-8 < in)
|
||||
|
||||
.Lstart:
|
||||
addq $8, %rsi / increment in
|
||||
addq $8, %rdi / increment out
|
||||
|
||||
/ generate the next 8 bytes of the rc4 stream into %r8
|
||||
movq $8, %r11 / byte counter
|
||||
1: addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
decb %r11b
|
||||
rorq $8, %r8 / (ror does not change ZF)
|
||||
jnz 1b
|
||||
|
||||
/ xor 8 bytes
|
||||
xorq -8(%rsi), %r8
|
||||
cmpq %r9, %rsi / cmp in+len-8 with in
|
||||
movq %r8, -8(%rdi)
|
||||
jle .Lstart / jump if (in <= in+len-8)
|
||||
|
||||
.Lend:
|
||||
addq $8, %r9 / tmp = in+len
|
||||
|
||||
/ handle the last bytes, one by one
|
||||
1: cmpq %rsi, %r9 / cmp in with in+len
|
||||
jle .Lfinished / jump if (in+len <= in)
|
||||
addb %al, %dl / y += tx
|
||||
movl 0(%rbp,%rdx,8), %ebx / ty = d[y]
|
||||
movl %ebx, 0(%rbp,%rcx,8) / d[x] = ty
|
||||
addb %al, %bl / val = ty + tx
|
||||
movl %eax, 0(%rbp,%rdx,8) / d[y] = tx
|
||||
incb %cl / x++ (NEXT ROUND)
|
||||
movl 0(%rbp,%rcx,8), %eax / tx = d[x] (NEXT ROUND)
|
||||
movb 0(%rbp,%rbx,8), %r8b / val = d[val]
|
||||
xorb (%rsi), %r8b / xor 1 byte
|
||||
movb %r8b, (%rdi)
|
||||
incq %rsi / in++
|
||||
incq %rdi / out++
|
||||
jmp 1b
|
||||
|
||||
.Lfinished:
|
||||
decq %rcx / x--
|
||||
movb %dl, -8(%rbp) / key->y = y
|
||||
movb %cl, -16(%rbp) / key->x = x
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
ret
|
||||
.L_ARCFOUR_end:
|
||||
.size ARCFOUR,.L_ARCFOUR_end-ARCFOUR
|
||||
@@ -1,640 +0,0 @@
|
||||
/* arcfour.c - the arc four algorithm.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* See NOTES ON UMRs, Unititialized Memory Reads, below. */
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "blapi.h"
|
||||
|
||||
/* Architecture-dependent defines */
|
||||
|
||||
#if defined(SOLARIS) || defined(HPUX) || defined(i386) || defined(IRIX) || \
|
||||
defined(_WIN64)
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
#define CONVERT_TO_WORDS
|
||||
#endif
|
||||
|
||||
#if defined(AIX) || defined(OSF1) || defined(NSS_BEVAND_ARCFOUR)
|
||||
/* Treat array variables as longs, not bytes, on CPUs that take
|
||||
* much longer to write bytes than to write longs, or when using
|
||||
* assembler code that required it.
|
||||
*/
|
||||
#define USE_WORD
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#undef WORD
|
||||
#define WORD ARC4WORD
|
||||
#endif
|
||||
|
||||
#if (defined(IS_64) && !defined(__sparc))
|
||||
typedef PRUint64 WORD;
|
||||
#else
|
||||
typedef PRUint32 WORD;
|
||||
#endif
|
||||
#define WORDSIZE sizeof(WORD)
|
||||
|
||||
#if defined(USE_WORD)
|
||||
typedef WORD Stype;
|
||||
#else
|
||||
typedef PRUint8 Stype;
|
||||
#endif
|
||||
|
||||
#define ARCFOUR_STATE_SIZE 256
|
||||
|
||||
#define MASK1BYTE (WORD)(0xff)
|
||||
|
||||
#define SWAP(a, b) \
|
||||
tmp = a; \
|
||||
a = b; \
|
||||
b = tmp;
|
||||
|
||||
/*
|
||||
* State information for stream cipher.
|
||||
*/
|
||||
struct RC4ContextStr
|
||||
{
|
||||
#if defined(NSS_ARCFOUR_IJ_B4_S) || defined(NSS_BEVAND_ARCFOUR)
|
||||
Stype i;
|
||||
Stype j;
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
#else
|
||||
Stype S[ARCFOUR_STATE_SIZE];
|
||||
Stype i;
|
||||
Stype j;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* array indices [0..255] to initialize cx->S array (faster than loop).
|
||||
*/
|
||||
static const Stype Kinit[256] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
RC4Context *
|
||||
RC4_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(RC4Context);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
|
||||
const unsigned char * unused1, int unused2,
|
||||
unsigned int unused3, unsigned int unused4)
|
||||
{
|
||||
int i;
|
||||
PRUint8 j, tmp;
|
||||
PRUint8 K[256];
|
||||
PRUint8 *L;
|
||||
/* verify the key length. */
|
||||
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
|
||||
if (len < 0 || len >= ARCFOUR_STATE_SIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize the state using array indices. */
|
||||
memcpy(cx->S, Kinit, sizeof cx->S);
|
||||
/* Fill in K repeatedly with values from key. */
|
||||
L = K;
|
||||
for (i = sizeof K; i > len; i-= len) {
|
||||
memcpy(L, key, len);
|
||||
L += len;
|
||||
}
|
||||
memcpy(L, key, i);
|
||||
/* Stir the state of the generator. At this point it is assumed
|
||||
* that the key is the size of the state buffer. If this is not
|
||||
* the case, the key bytes are repeated to fill the buffer.
|
||||
*/
|
||||
j = 0;
|
||||
#define ARCFOUR_STATE_STIR(ii) \
|
||||
j = j + cx->S[ii] + K[ii]; \
|
||||
SWAP(cx->S[ii], cx->S[j]);
|
||||
for (i=0; i<ARCFOUR_STATE_SIZE; i++) {
|
||||
ARCFOUR_STATE_STIR(i);
|
||||
}
|
||||
cx->i = 0;
|
||||
cx->j = 0;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a new generator.
|
||||
*/
|
||||
RC4Context *
|
||||
RC4_CreateContext(const unsigned char *key, int len)
|
||||
{
|
||||
RC4Context *cx = RC4_AllocateContext();
|
||||
if (cx) {
|
||||
SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
cx = NULL;
|
||||
}
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
|
||||
{
|
||||
if (freeit)
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
}
|
||||
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
extern void ARCFOUR(RC4Context *cx, WORD inputLen,
|
||||
const unsigned char *input, unsigned char *output);
|
||||
#else
|
||||
/*
|
||||
* Generate the next byte in the stream.
|
||||
*/
|
||||
#define ARCFOUR_NEXT_BYTE() \
|
||||
tmpSi = cx->S[++tmpi]; \
|
||||
tmpj += tmpSi; \
|
||||
tmpSj = cx->S[tmpj]; \
|
||||
cx->S[tmpi] = tmpSj; \
|
||||
cx->S[tmpj] = tmpSi; \
|
||||
t = tmpSi + tmpSj;
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Straight ARCFOUR op. No optimization.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_no_opt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index=0; index < inputLen; index++) {
|
||||
/* Generate next byte from stream. */
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
/* output = next stream byte XOR next input byte */
|
||||
output[index] = cx->S[t] ^ input[index];
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONVERT_TO_WORDS
|
||||
/*
|
||||
* Byte-at-a-time ARCFOUR, unrolling the loop into 8 pieces.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_unrolled(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint8 t;
|
||||
Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
int index;
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
for (index = inputLen / 8; index-- > 0; input += 8, output += 8) {
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[0] = cx->S[t] ^ input[0];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[1] = cx->S[t] ^ input[1];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[2] = cx->S[t] ^ input[2];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[3] = cx->S[t] ^ input[3];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[4] = cx->S[t] ^ input[4];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[5] = cx->S[t] ^ input[5];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[6] = cx->S[t] ^ input[6];
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[7] = cx->S[t] ^ input[7];
|
||||
}
|
||||
index = inputLen % 8;
|
||||
if (index) {
|
||||
input += index;
|
||||
output += index;
|
||||
switch (index) {
|
||||
case 7:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-7] = cx->S[t] ^ input[-7]; /* FALLTHRU */
|
||||
case 6:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-6] = cx->S[t] ^ input[-6]; /* FALLTHRU */
|
||||
case 5:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-5] = cx->S[t] ^ input[-5]; /* FALLTHRU */
|
||||
case 4:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-4] = cx->S[t] ^ input[-4]; /* FALLTHRU */
|
||||
case 3:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-3] = cx->S[t] ^ input[-3]; /* FALLTHRU */
|
||||
case 2:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-2] = cx->S[t] ^ input[-2]; /* FALLTHRU */
|
||||
case 1:
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
output[-1] = cx->S[t] ^ input[-1]; /* FALLTHRU */
|
||||
default:
|
||||
/* FALLTHRU */
|
||||
; /* hp-ux build breaks without this */
|
||||
}
|
||||
}
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT4BYTES_L(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n ); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24);
|
||||
#else
|
||||
#define ARCFOUR_NEXT4BYTES_B(n) \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 24); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 16); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n + 8); \
|
||||
ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n );
|
||||
#endif
|
||||
|
||||
#if (defined(IS_64) && !defined(__sparc)) || defined(NSS_USE_64)
|
||||
/* 64-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); ARCFOUR_NEXT4BYTES_L(32); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(32); ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#else
|
||||
/* 32-bit wordsize */
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_L(0); }
|
||||
#else
|
||||
#define ARCFOUR_NEXT_WORD() \
|
||||
{ streamWord = 0; ARCFOUR_NEXT4BYTES_B(0); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define RSH <<
|
||||
#define LSH >>
|
||||
#else
|
||||
#define RSH >>
|
||||
#define LSH <<
|
||||
#endif
|
||||
|
||||
#ifdef CONVERT_TO_WORDS
|
||||
/* NOTE about UMRs, Uninitialized Memory Reads.
|
||||
*
|
||||
* This code reads all input data a WORD at a time, rather than byte at
|
||||
* a time, and writes all output data a WORD at a time. Shifting and
|
||||
* masking is used to remove unwanted data and realign bytes when
|
||||
* needed. The first and last words of output are read, modified, and
|
||||
* written when needed to preserve any unchanged bytes. This is a huge
|
||||
* win on machines with high memory latency.
|
||||
*
|
||||
* However, when the input and output buffers do not begin and end on WORD
|
||||
* boundaries, and the WORDS in memory that contain the first and last
|
||||
* bytes of those buffers contain uninitialized data, then this code will
|
||||
* read those uninitialized bytes, causing a UMR error to be reported by
|
||||
* some tools.
|
||||
*
|
||||
* These UMRs are NOT a problem, NOT errors, and do NOT need to be "fixed".
|
||||
*
|
||||
* All the words read and written contain at least one byte that is
|
||||
* part of the input data or output data. No words are read or written
|
||||
* that do not contain data that is part of the buffer. Therefore,
|
||||
* these UMRs cannot cause page faults or other problems unless the
|
||||
* buffers have been assigned to improper addresses that would cause
|
||||
* page faults with or without UMRs.
|
||||
*/
|
||||
static SECStatus
|
||||
rc4_wordconv(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
ptrdiff_t inOffset = (ptrdiff_t)input % WORDSIZE;
|
||||
ptrdiff_t outOffset = (ptrdiff_t)output % WORDSIZE;
|
||||
register WORD streamWord, mask;
|
||||
register WORD *pInWord, *pOutWord;
|
||||
register WORD inWord, nextInWord;
|
||||
PRUint8 t;
|
||||
register Stype tmpSi, tmpSj;
|
||||
register PRUint8 tmpi = cx->i;
|
||||
register PRUint8 tmpj = cx->j;
|
||||
unsigned int byteCount;
|
||||
unsigned int bufShift, invBufShift;
|
||||
int i;
|
||||
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (inputLen < 2*WORDSIZE) {
|
||||
/* Ignore word conversion, do byte-at-a-time */
|
||||
return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
pInWord = (WORD *)(input - inOffset);
|
||||
if (inOffset < outOffset) {
|
||||
bufShift = 8*(outOffset - inOffset);
|
||||
invBufShift = 8*WORDSIZE - bufShift;
|
||||
} else {
|
||||
invBufShift = 8*(inOffset - outOffset);
|
||||
bufShift = 8*WORDSIZE - invBufShift;
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 1: */
|
||||
/* If the first output word is partial, consume the bytes in the */
|
||||
/* first partial output word by loading one or two words of */
|
||||
/* input and shifting them accordingly. Otherwise, just load */
|
||||
/* in the first word of input. At the end of this block, at */
|
||||
/* least one partial word of input should ALWAYS be loaded. */
|
||||
/*****************************************************************/
|
||||
if (outOffset) {
|
||||
/* Generate input and stream words aligned relative to the
|
||||
* partial output buffer.
|
||||
*/
|
||||
byteCount = WORDSIZE - outOffset;
|
||||
pOutWord = (WORD *)(output - outOffset);
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = WORDSIZE - byteCount; i < WORDSIZE; i++) {
|
||||
#else
|
||||
for (i = byteCount - 1; i >= 0; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
inWord = *pInWord++; /* UMR? see comments above. */
|
||||
/* If buffers are relatively misaligned, shift the bytes in inWord
|
||||
* to be aligned to the output buffer.
|
||||
*/
|
||||
nextInWord = 0;
|
||||
if (inOffset < outOffset) {
|
||||
/* Have more bytes than needed, shift remainder into nextInWord */
|
||||
nextInWord = inWord LSH 8*(inOffset + byteCount);
|
||||
inWord = inWord RSH bufShift;
|
||||
} else if (inOffset > outOffset) {
|
||||
/* Didn't get enough bytes from current input word, load another
|
||||
* word and then shift remainder into nextInWord.
|
||||
*/
|
||||
nextInWord = *pInWord++;
|
||||
inWord = (inWord LSH invBufShift) |
|
||||
(nextInWord RSH bufShift);
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
}
|
||||
/* Store output of first partial word */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
/* UMR? See comments above. */
|
||||
|
||||
/* Consumed byteCount bytes of input */
|
||||
inputLen -= byteCount;
|
||||
/* move to next word of output */
|
||||
pOutWord++;
|
||||
/* inWord has been consumed, but there may be bytes in nextInWord */
|
||||
inWord = nextInWord;
|
||||
} else {
|
||||
/* output is word-aligned */
|
||||
pOutWord = (WORD *)output;
|
||||
if (inOffset) {
|
||||
/* Input is not word-aligned. The first word load of input
|
||||
* will not produce a full word of input bytes, so one word
|
||||
* must be pre-loaded. The main loop below will load in the
|
||||
* next input word and shift some of its bytes into inWord
|
||||
* in order to create a full input word. Note that the main
|
||||
* loop must execute at least once because the input must
|
||||
* be at least two words.
|
||||
*/
|
||||
inWord = *pInWord++; /* UMR? see comments above. */
|
||||
inWord = inWord LSH invBufShift;
|
||||
} else {
|
||||
/* Input is word-aligned. The first word load of input
|
||||
* will produce a full word of input bytes, so nothing
|
||||
* needs to be loaded here.
|
||||
*/
|
||||
inWord = 0;
|
||||
}
|
||||
}
|
||||
/* Output buffer is aligned, inOffset is now measured relative to
|
||||
* outOffset (and not a word boundary).
|
||||
*/
|
||||
inOffset = (inOffset + WORDSIZE - outOffset) % WORDSIZE;
|
||||
/*****************************************************************/
|
||||
/* Step 2: main loop */
|
||||
/* At this point the output buffer is word-aligned. Any unused */
|
||||
/* bytes from above will be in inWord (shifted correctly). If */
|
||||
/* the input buffer is unaligned relative to the output buffer, */
|
||||
/* shifting has to be done. */
|
||||
/*****************************************************************/
|
||||
if (inOffset) {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
nextInWord = *pInWord++;
|
||||
inWord |= nextInWord RSH bufShift;
|
||||
nextInWord = nextInWord LSH invBufShift;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
inWord = nextInWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
/* If the amount of remaining input is greater than the amount
|
||||
* bytes pulled from the current input word, need to do another
|
||||
* word load. What's left in inWord will be consumed in step 3.
|
||||
*/
|
||||
if (inputLen > WORDSIZE - inOffset)
|
||||
inWord |= *pInWord RSH bufShift; /* UMR? See above. */
|
||||
} else {
|
||||
for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) {
|
||||
inWord = *pInWord++;
|
||||
ARCFOUR_NEXT_WORD();
|
||||
*pOutWord++ = inWord ^ streamWord;
|
||||
}
|
||||
if (inputLen == 0) {
|
||||
/* Nothing left to do. */
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
} else {
|
||||
/* A partial input word remains at the tail. Load it.
|
||||
* The relevant bytes will be consumed in step 3.
|
||||
*/
|
||||
inWord = *pInWord; /* UMR? See comments above */
|
||||
}
|
||||
}
|
||||
/*****************************************************************/
|
||||
/* Step 3: */
|
||||
/* A partial word of input remains, and it is already loaded */
|
||||
/* into nextInWord. Shift appropriately and consume the bytes */
|
||||
/* used in the partial word. */
|
||||
/*****************************************************************/
|
||||
mask = streamWord = 0;
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
for (i = 0; i < inputLen; ++i) {
|
||||
#else
|
||||
for (i = WORDSIZE - 1; i >= WORDSIZE - inputLen; --i) {
|
||||
#endif
|
||||
ARCFOUR_NEXT_BYTE();
|
||||
streamWord |= (WORD)(cx->S[t]) << 8*i;
|
||||
mask |= MASK1BYTE << 8*i;
|
||||
} /* } */
|
||||
/* UMR? See comments above. */
|
||||
*pOutWord = (*pOutWord & ~mask) | ((inWord ^ streamWord) & mask);
|
||||
cx->i = tmpi;
|
||||
cx->j = tmpj;
|
||||
return SECSuccess;
|
||||
}
|
||||
#endif
|
||||
#endif /* NSS_BEVAND_ARCFOUR */
|
||||
|
||||
SECStatus
|
||||
RC4_Encrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
ARCFOUR(cx, inputLen, input, output);
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
#elif defined( CONVERT_TO_WORDS )
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PORT_Assert(maxOutputLen >= inputLen);
|
||||
if (maxOutputLen < inputLen) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* decrypt and encrypt are same operation. */
|
||||
#if defined(NSS_BEVAND_ARCFOUR)
|
||||
ARCFOUR(cx, inputLen, input, output);
|
||||
*outputLen = inputLen;
|
||||
return SECSuccess;
|
||||
#elif defined( CONVERT_TO_WORDS )
|
||||
/* Convert the byte-stream to a word-stream */
|
||||
return rc4_wordconv(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#else
|
||||
/* Operate on bytes, but unroll the main loop */
|
||||
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef CONVERT_TO_WORDS
|
||||
#undef USE_WORD
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,380 +0,0 @@
|
||||
/*
|
||||
* blapit.h - public data structures for the crypto library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: blapit.h,v 1.20 2007-02-28 19:47:37 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _BLAPIT_H_
|
||||
#define _BLAPIT_H_
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "prlink.h"
|
||||
#include "plarena.h"
|
||||
#include "ecl-exp.h"
|
||||
|
||||
|
||||
/* RC2 operation modes */
|
||||
#define NSS_RC2 0
|
||||
#define NSS_RC2_CBC 1
|
||||
|
||||
/* RC5 operation modes */
|
||||
#define NSS_RC5 0
|
||||
#define NSS_RC5_CBC 1
|
||||
|
||||
/* DES operation modes */
|
||||
#define NSS_DES 0
|
||||
#define NSS_DES_CBC 1
|
||||
#define NSS_DES_EDE3 2
|
||||
#define NSS_DES_EDE3_CBC 3
|
||||
|
||||
#define DES_KEY_LENGTH 8 /* Bytes */
|
||||
|
||||
/* AES operation modes */
|
||||
#define NSS_AES 0
|
||||
#define NSS_AES_CBC 1
|
||||
|
||||
/* Camellia operation modes */
|
||||
#define NSS_CAMELLIA 0
|
||||
#define NSS_CAMELLIA_CBC 1
|
||||
|
||||
#define DSA_SIGNATURE_LEN 40 /* Bytes */
|
||||
#define DSA_SUBPRIME_LEN 20 /* Bytes */
|
||||
|
||||
/* XXX We shouldn't have to hard code this limit. For
|
||||
* now, this is the quickest way to support ECDSA signature
|
||||
* processing (ECDSA signature lengths depend on curve
|
||||
* size). This limit is sufficient for curves upto
|
||||
* 576 bits.
|
||||
*/
|
||||
#define MAX_ECKEY_LEN 72 /* Bytes */
|
||||
|
||||
/*
|
||||
* Number of bytes each hash algorithm produces
|
||||
*/
|
||||
#define MD2_LENGTH 16 /* Bytes */
|
||||
#define MD5_LENGTH 16 /* Bytes */
|
||||
#define SHA1_LENGTH 20 /* Bytes */
|
||||
#define SHA256_LENGTH 32 /* bytes */
|
||||
#define SHA384_LENGTH 48 /* bytes */
|
||||
#define SHA512_LENGTH 64 /* bytes */
|
||||
#define HASH_LENGTH_MAX SHA512_LENGTH
|
||||
|
||||
/*
|
||||
* Input block size for each hash algorithm.
|
||||
*/
|
||||
|
||||
#define MD2_BLOCK_LENGTH 64 /* bytes */
|
||||
#define MD5_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA1_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA256_BLOCK_LENGTH 64 /* bytes */
|
||||
#define SHA384_BLOCK_LENGTH 128 /* bytes */
|
||||
#define SHA512_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 CAMELLIA_BLOCK_SIZE 16 /* bytes */
|
||||
|
||||
#define NSS_FREEBL_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
/*
|
||||
* These values come from the initial key size limits from the PKCS #11
|
||||
* module. They may be arbitrarily adjusted to any value freebl supports.
|
||||
*/
|
||||
#define RSA_MIN_MODULUS_BITS 128
|
||||
#define RSA_MAX_MODULUS_BITS 8192
|
||||
#define RSA_MAX_EXPONENT_BITS 64
|
||||
#define DH_MIN_P_BITS 128
|
||||
#define DH_MAX_P_BITS 2236
|
||||
|
||||
/*
|
||||
* The FIPS 186 algorithm for generating primes P and Q allows only 9
|
||||
* distinct values for the length of P, and only one value for the
|
||||
* length of Q.
|
||||
* The algorithm uses a variable j to indicate which of the 9 lengths
|
||||
* of P is to be used.
|
||||
* The following table relates j to the lengths of P and Q in bits.
|
||||
*
|
||||
* j bits in P bits in Q
|
||||
* _ _________ _________
|
||||
* 0 512 160
|
||||
* 1 576 160
|
||||
* 2 640 160
|
||||
* 3 704 160
|
||||
* 4 768 160
|
||||
* 5 832 160
|
||||
* 6 896 160
|
||||
* 7 960 160
|
||||
* 8 1024 160
|
||||
*
|
||||
* The FIPS-186 compliant PQG generator takes j as an input parameter.
|
||||
*/
|
||||
|
||||
#define DSA_Q_BITS 160
|
||||
#define DSA_MAX_P_BITS 1024
|
||||
#define DSA_MIN_P_BITS 512
|
||||
|
||||
/*
|
||||
* function takes desired number of bits in P,
|
||||
* returns index (0..8) or -1 if number of bits is invalid.
|
||||
*/
|
||||
#define PQG_PBITS_TO_INDEX(bits) \
|
||||
(((bits) < 512 || (bits) > 1024 || (bits) % 64) ? \
|
||||
-1 : (int)((bits)-512)/64)
|
||||
|
||||
/*
|
||||
* function takes index (0-8)
|
||||
* returns number of bits in P for that index, or -1 if index is invalid.
|
||||
*/
|
||||
#define PQG_INDEX_TO_PBITS(j) (((unsigned)(j) > 8) ? -1 : (512 + 64 * (j)))
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Opaque objects
|
||||
*/
|
||||
|
||||
struct DESContextStr ;
|
||||
struct RC2ContextStr ;
|
||||
struct RC4ContextStr ;
|
||||
struct RC5ContextStr ;
|
||||
struct AESContextStr ;
|
||||
struct CamelliaContextStr ;
|
||||
struct MD2ContextStr ;
|
||||
struct MD5ContextStr ;
|
||||
struct SHA1ContextStr ;
|
||||
struct SHA256ContextStr ;
|
||||
struct SHA512ContextStr ;
|
||||
struct AESKeyWrapContextStr ;
|
||||
|
||||
typedef struct DESContextStr DESContext;
|
||||
typedef struct RC2ContextStr RC2Context;
|
||||
typedef struct RC4ContextStr RC4Context;
|
||||
typedef struct RC5ContextStr RC5Context;
|
||||
typedef struct AESContextStr AESContext;
|
||||
typedef struct CamelliaContextStr CamelliaContext;
|
||||
typedef struct MD2ContextStr MD2Context;
|
||||
typedef struct MD5ContextStr MD5Context;
|
||||
typedef struct SHA1ContextStr SHA1Context;
|
||||
typedef struct SHA256ContextStr SHA256Context;
|
||||
typedef struct SHA512ContextStr SHA512Context;
|
||||
/* SHA384Context is really a SHA512ContextStr. This is not a mistake. */
|
||||
typedef struct SHA512ContextStr SHA384Context;
|
||||
typedef struct AESKeyWrapContextStr AESKeyWrapContext;
|
||||
|
||||
/***************************************************************************
|
||||
** RSA Public and Private Key structures
|
||||
*/
|
||||
|
||||
/* member names from PKCS#1, section 7.1 */
|
||||
struct RSAPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
};
|
||||
typedef struct RSAPublicKeyStr RSAPublicKey;
|
||||
|
||||
/* member names from PKCS#1, section 7.2 */
|
||||
struct RSAPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem version;
|
||||
SECItem modulus;
|
||||
SECItem publicExponent;
|
||||
SECItem privateExponent;
|
||||
SECItem prime1;
|
||||
SECItem prime2;
|
||||
SECItem exponent1;
|
||||
SECItem exponent2;
|
||||
SECItem coefficient;
|
||||
};
|
||||
typedef struct RSAPrivateKeyStr RSAPrivateKey;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** DSA Public and Private Key and related structures
|
||||
*/
|
||||
|
||||
struct PQGParamsStr {
|
||||
PRArenaPool *arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem subPrime; /* q */
|
||||
SECItem base; /* g */
|
||||
/* XXX chrisk: this needs to be expanded to hold j and validationParms (RFC2459 7.3.2) */
|
||||
};
|
||||
typedef struct PQGParamsStr PQGParams;
|
||||
|
||||
struct PQGVerifyStr {
|
||||
PRArenaPool * arena; /* includes this struct, seed, & h. */
|
||||
unsigned int counter;
|
||||
SECItem seed;
|
||||
SECItem h;
|
||||
};
|
||||
typedef struct PQGVerifyStr PQGVerify;
|
||||
|
||||
struct DSAPublicKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DSAPublicKeyStr DSAPublicKey;
|
||||
|
||||
struct DSAPrivateKeyStr {
|
||||
PQGParams params;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DSAPrivateKeyStr DSAPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Diffie-Hellman Public and Private Key and related structures
|
||||
** Structure member names suggested by PKCS#3.
|
||||
*/
|
||||
|
||||
struct DHParamsStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime; /* p */
|
||||
SECItem base; /* g */
|
||||
};
|
||||
typedef struct DHParamsStr DHParams;
|
||||
|
||||
struct DHPublicKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
};
|
||||
typedef struct DHPublicKeyStr DHPublicKey;
|
||||
|
||||
struct DHPrivateKeyStr {
|
||||
PRArenaPool * arena;
|
||||
SECItem prime;
|
||||
SECItem base;
|
||||
SECItem publicValue;
|
||||
SECItem privateValue;
|
||||
};
|
||||
typedef struct DHPrivateKeyStr DHPrivateKey;
|
||||
|
||||
/***************************************************************************
|
||||
** Data structures used for elliptic curve parameters and
|
||||
** public and private keys.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The ECParams data structures can encode elliptic curve
|
||||
** parameters for both GFp and GF2m curves.
|
||||
*/
|
||||
|
||||
typedef enum { ec_params_explicit,
|
||||
ec_params_named
|
||||
} ECParamsType;
|
||||
|
||||
typedef enum { ec_field_GFp = 1,
|
||||
ec_field_GF2m
|
||||
} ECFieldType;
|
||||
|
||||
struct ECFieldIDStr {
|
||||
int size; /* field size in bits */
|
||||
ECFieldType type;
|
||||
union {
|
||||
SECItem prime; /* prime p for (GFp) */
|
||||
SECItem poly; /* irreducible binary polynomial for (GF2m) */
|
||||
} u;
|
||||
int k1; /* first coefficient of pentanomial or
|
||||
* the only coefficient of trinomial
|
||||
*/
|
||||
int k2; /* two remaining coefficients of pentanomial */
|
||||
int k3;
|
||||
};
|
||||
typedef struct ECFieldIDStr ECFieldID;
|
||||
|
||||
struct ECCurveStr {
|
||||
SECItem a; /* contains octet stream encoding of
|
||||
* field element (X9.62 section 4.3.3)
|
||||
*/
|
||||
SECItem b;
|
||||
SECItem seed;
|
||||
};
|
||||
typedef struct ECCurveStr ECCurve;
|
||||
|
||||
struct ECParamsStr {
|
||||
PRArenaPool * arena;
|
||||
ECParamsType type;
|
||||
ECFieldID fieldID;
|
||||
ECCurve curve;
|
||||
SECItem base;
|
||||
SECItem order;
|
||||
int cofactor;
|
||||
SECItem DEREncoding;
|
||||
ECCurveName name;
|
||||
SECItem curveOID;
|
||||
};
|
||||
typedef struct ECParamsStr ECParams;
|
||||
|
||||
struct ECPublicKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* elliptic curve point encoded as
|
||||
* octet stream.
|
||||
*/
|
||||
};
|
||||
typedef struct ECPublicKeyStr ECPublicKey;
|
||||
|
||||
struct ECPrivateKeyStr {
|
||||
ECParams ecParams;
|
||||
SECItem publicValue; /* encoded ec point */
|
||||
SECItem privateValue; /* private big integer */
|
||||
SECItem version; /* As per SEC 1, Appendix C, Section C.4 */
|
||||
};
|
||||
typedef struct ECPrivateKeyStr ECPrivateKey;
|
||||
|
||||
typedef void * (*BLapiAllocateFunc)(void);
|
||||
typedef void (*BLapiDestroyContextFunc)(void *cx, PRBool freeit);
|
||||
typedef SECStatus (*BLapiInitContextFunc)(void *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *,
|
||||
int,
|
||||
unsigned int ,
|
||||
unsigned int );
|
||||
typedef SECStatus (*BLapiEncrypt)(void *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
#endif /* _BLAPIT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,79 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Camellia code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* NTT(Nippon Telegraph and Telephone Corporation).
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* $Id: camellia.h,v 1.1 2007-02-28 19:47:37 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _CAMELLIA_H_
|
||||
#define _CAMELLIA_H_ 1
|
||||
|
||||
#define CAMELLIA_BLOCK_SIZE 16 /* bytes */
|
||||
#define CAMELLIA_MIN_KEYSIZE 16 /* bytes */
|
||||
#define CAMELLIA_MAX_KEYSIZE 32 /* bytes */
|
||||
|
||||
#define CAMELLIA_MAX_EXPANDEDKEY (34*2) /* 32bit unit */
|
||||
|
||||
typedef PRUint32 KEY_TABLE_TYPE[CAMELLIA_MAX_EXPANDEDKEY];
|
||||
|
||||
typedef SECStatus CamelliaFunc(CamelliaContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
typedef SECStatus CamelliaBlockFunc(const PRUint32 *subkey,
|
||||
unsigned char *output,
|
||||
const unsigned char *input);
|
||||
|
||||
/* CamelliaContextStr
|
||||
*
|
||||
* Values which maintain the state for Camellia encryption/decryption.
|
||||
*
|
||||
* keysize - the number of key bits
|
||||
* worker - the encryption/decryption function to use with this context
|
||||
* iv - initialization vector for CBC mode
|
||||
* expandedKey - the round keys in 4-byte words
|
||||
*/
|
||||
struct CamelliaContextStr
|
||||
{
|
||||
PRUint32 keysize; /* bytes */
|
||||
CamelliaFunc *worker;
|
||||
PRUint32 expandedKey[CAMELLIA_MAX_EXPANDEDKEY];
|
||||
PRUint8 iv[CAMELLIA_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
#endif /* _CAMELLIA_H_ */
|
||||
@@ -1,119 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# only do this in the outermost freebl build.
|
||||
ifndef FREEBL_CHILD_BUILD
|
||||
|
||||
# We're going to change this build so that it builds libfreebl.a with
|
||||
# just loader.c. Then we have to build this directory twice again to
|
||||
# build the two DSOs.
|
||||
# To build libfreebl.a with just loader.c, we must now override many
|
||||
# of the make variables setup by the prior inclusion of CORECONF's config.mk
|
||||
|
||||
CSRCS = loader.c
|
||||
SIMPLE_OBJS = $(CSRCS:.c=$(OBJ_SUFFIX))
|
||||
OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(SIMPLE_OBJS))
|
||||
ALL_TRASH := $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \
|
||||
$(NOSUCHFILE) so_locations
|
||||
|
||||
# this is not a recursive child make. We make a static lib. (archive)
|
||||
|
||||
# Override the values defined in coreconf's ruleset.mk.
|
||||
#
|
||||
# - (1) LIBRARY: a static (archival) library
|
||||
# - (2) SHARED_LIBRARY: a shared (dynamic link) library
|
||||
# - (3) IMPORT_LIBRARY: an import library, used only on Windows
|
||||
# - (4) PROGRAM: an executable binary
|
||||
#
|
||||
# override these variables to prevent building a DSO/DLL.
|
||||
TARGETS = $(LIBRARY)
|
||||
SHARED_LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
else
|
||||
# This is a recursive child make. We build the shared lib.
|
||||
|
||||
TARGETS = $(SHARED_LIBRARY)
|
||||
LIBRARY =
|
||||
IMPORT_LIBRARY =
|
||||
PROGRAM =
|
||||
|
||||
ifeq ($(OS_TARGET), SunOS)
|
||||
OS_LIBS += -lkstat
|
||||
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
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib \
|
||||
-lnssutil3 \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
else # ! NS_USE_GCC
|
||||
EXTRA_SHARED_LIBS += \
|
||||
$(DIST)/lib/nssutil3.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \
|
||||
$(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \
|
||||
$(NULL)
|
||||
endif # NS_USE_GCC
|
||||
|
||||
else
|
||||
|
||||
EXTRA_SHARED_LIBS += \
|
||||
-L$(DIST)/lib \
|
||||
-lnssutil3 \
|
||||
-L$(NSPR_LIB_DIR) \
|
||||
-lplc4 \
|
||||
-lplds4 \
|
||||
-lnspr4 \
|
||||
$(NULL)
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
@@ -1,689 +0,0 @@
|
||||
/*
|
||||
* des.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Make key schedule from DES key.
|
||||
* Encrypt/Decrypt one 8-byte block.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h> /* for ptrdiff_t */
|
||||
/* #define USE_INDEXING 1 */
|
||||
|
||||
/*
|
||||
* The tables below are the 8 sbox functions, with the 6-bit input permutation
|
||||
* and the 32-bit output permutation pre-computed.
|
||||
* They are shifted circularly to the left 3 bits, which removes 2 shifts
|
||||
* and an or from each round by reducing the number of sboxes whose
|
||||
* indices cross word broundaries from 2 to 1.
|
||||
*/
|
||||
|
||||
static const HALF SP[8][64] = {
|
||||
/* Box S1 */ {
|
||||
0x04041000, 0x00000000, 0x00040000, 0x04041010,
|
||||
0x04040010, 0x00041010, 0x00000010, 0x00040000,
|
||||
0x00001000, 0x04041000, 0x04041010, 0x00001000,
|
||||
0x04001010, 0x04040010, 0x04000000, 0x00000010,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00041000,
|
||||
0x00041000, 0x04040000, 0x04040000, 0x04001010,
|
||||
0x00040010, 0x04000010, 0x04000010, 0x00040010,
|
||||
0x00000000, 0x00001010, 0x00041010, 0x04000000,
|
||||
0x00040000, 0x04041010, 0x00000010, 0x04040000,
|
||||
0x04041000, 0x04000000, 0x04000000, 0x00001000,
|
||||
0x04040010, 0x00040000, 0x00041000, 0x04000010,
|
||||
0x00001000, 0x00000010, 0x04001010, 0x00041010,
|
||||
0x04041010, 0x00040010, 0x04040000, 0x04001010,
|
||||
0x04000010, 0x00001010, 0x00041010, 0x04041000,
|
||||
0x00001010, 0x04001000, 0x04001000, 0x00000000,
|
||||
0x00040010, 0x00041000, 0x00000000, 0x04040010
|
||||
},
|
||||
/* Box S2 */ {
|
||||
0x00420082, 0x00020002, 0x00020000, 0x00420080,
|
||||
0x00400000, 0x00000080, 0x00400082, 0x00020082,
|
||||
0x00000082, 0x00420082, 0x00420002, 0x00000002,
|
||||
0x00020002, 0x00400000, 0x00000080, 0x00400082,
|
||||
0x00420000, 0x00400080, 0x00020082, 0x00000000,
|
||||
0x00000002, 0x00020000, 0x00420080, 0x00400002,
|
||||
0x00400080, 0x00000082, 0x00000000, 0x00420000,
|
||||
0x00020080, 0x00420002, 0x00400002, 0x00020080,
|
||||
0x00000000, 0x00420080, 0x00400082, 0x00400000,
|
||||
0x00020082, 0x00400002, 0x00420002, 0x00020000,
|
||||
0x00400002, 0x00020002, 0x00000080, 0x00420082,
|
||||
0x00420080, 0x00000080, 0x00020000, 0x00000002,
|
||||
0x00020080, 0x00420002, 0x00400000, 0x00000082,
|
||||
0x00400080, 0x00020082, 0x00000082, 0x00400080,
|
||||
0x00420000, 0x00000000, 0x00020002, 0x00020080,
|
||||
0x00000002, 0x00400082, 0x00420082, 0x00420000
|
||||
},
|
||||
/* Box S3 */ {
|
||||
0x00000820, 0x20080800, 0x00000000, 0x20080020,
|
||||
0x20000800, 0x00000000, 0x00080820, 0x20000800,
|
||||
0x00080020, 0x20000020, 0x20000020, 0x00080000,
|
||||
0x20080820, 0x00080020, 0x20080000, 0x00000820,
|
||||
0x20000000, 0x00000020, 0x20080800, 0x00000800,
|
||||
0x00080800, 0x20080000, 0x20080020, 0x00080820,
|
||||
0x20000820, 0x00080800, 0x00080000, 0x20000820,
|
||||
0x00000020, 0x20080820, 0x00000800, 0x20000000,
|
||||
0x20080800, 0x20000000, 0x00080020, 0x00000820,
|
||||
0x00080000, 0x20080800, 0x20000800, 0x00000000,
|
||||
0x00000800, 0x00080020, 0x20080820, 0x20000800,
|
||||
0x20000020, 0x00000800, 0x00000000, 0x20080020,
|
||||
0x20000820, 0x00080000, 0x20000000, 0x20080820,
|
||||
0x00000020, 0x00080820, 0x00080800, 0x20000020,
|
||||
0x20080000, 0x20000820, 0x00000820, 0x20080000,
|
||||
0x00080820, 0x00000020, 0x20080020, 0x00080800
|
||||
},
|
||||
/* Box S4 */ {
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008200, 0x02000204, 0x02000004, 0x00008004,
|
||||
0x00000000, 0x02008000, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x02000200, 0x02000004,
|
||||
0x00000004, 0x00008000, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008004, 0x00008200,
|
||||
0x02000204, 0x00000004, 0x00008200, 0x02000200,
|
||||
0x00008000, 0x02008200, 0x02008204, 0x00000204,
|
||||
0x02000200, 0x02000004, 0x02008000, 0x02008204,
|
||||
0x00000204, 0x00000000, 0x00000000, 0x02008000,
|
||||
0x00008200, 0x02000200, 0x02000204, 0x00000004,
|
||||
0x02008004, 0x00008204, 0x00008204, 0x00000200,
|
||||
0x02008204, 0x00000204, 0x00000004, 0x00008000,
|
||||
0x02000004, 0x00008004, 0x02008200, 0x02000204,
|
||||
0x00008004, 0x00008200, 0x02000000, 0x02008004,
|
||||
0x00000200, 0x02000000, 0x00008000, 0x02008200
|
||||
},
|
||||
/* Box S5 */ {
|
||||
0x00000400, 0x08200400, 0x08200000, 0x08000401,
|
||||
0x00200000, 0x00000400, 0x00000001, 0x08200000,
|
||||
0x00200401, 0x00200000, 0x08000400, 0x00200401,
|
||||
0x08000401, 0x08200001, 0x00200400, 0x00000001,
|
||||
0x08000000, 0x00200001, 0x00200001, 0x00000000,
|
||||
0x00000401, 0x08200401, 0x08200401, 0x08000400,
|
||||
0x08200001, 0x00000401, 0x00000000, 0x08000001,
|
||||
0x08200400, 0x08000000, 0x08000001, 0x00200400,
|
||||
0x00200000, 0x08000401, 0x00000400, 0x08000000,
|
||||
0x00000001, 0x08200000, 0x08000401, 0x00200401,
|
||||
0x08000400, 0x00000001, 0x08200001, 0x08200400,
|
||||
0x00200401, 0x00000400, 0x08000000, 0x08200001,
|
||||
0x08200401, 0x00200400, 0x08000001, 0x08200401,
|
||||
0x08200000, 0x00000000, 0x00200001, 0x08000001,
|
||||
0x00200400, 0x08000400, 0x00000401, 0x00200000,
|
||||
0x00000000, 0x00200001, 0x08200400, 0x00000401
|
||||
},
|
||||
/* Box S6 */ {
|
||||
0x80000040, 0x81000000, 0x00010000, 0x81010040,
|
||||
0x81000000, 0x00000040, 0x81010040, 0x01000000,
|
||||
0x80010000, 0x01010040, 0x01000000, 0x80000040,
|
||||
0x01000040, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x00000000, 0x01000040, 0x80010040, 0x00010000,
|
||||
0x01010000, 0x80010040, 0x00000040, 0x81000040,
|
||||
0x81000040, 0x00000000, 0x01010040, 0x81010000,
|
||||
0x00010040, 0x01010000, 0x81010000, 0x80000000,
|
||||
0x80010000, 0x00000040, 0x81000040, 0x01010000,
|
||||
0x81010040, 0x01000000, 0x00010040, 0x80000040,
|
||||
0x01000000, 0x80010000, 0x80000000, 0x00010040,
|
||||
0x80000040, 0x81010040, 0x01010000, 0x81000000,
|
||||
0x01010040, 0x81010000, 0x00000000, 0x81000040,
|
||||
0x00000040, 0x00010000, 0x81000000, 0x01010040,
|
||||
0x00010000, 0x01000040, 0x80010040, 0x00000000,
|
||||
0x81010000, 0x80000000, 0x01000040, 0x80010040
|
||||
},
|
||||
/* Box S7 */ {
|
||||
0x00800000, 0x10800008, 0x10002008, 0x00000000,
|
||||
0x00002000, 0x10002008, 0x00802008, 0x10802000,
|
||||
0x10802008, 0x00800000, 0x00000000, 0x10000008,
|
||||
0x00000008, 0x10000000, 0x10800008, 0x00002008,
|
||||
0x10002000, 0x00802008, 0x00800008, 0x10002000,
|
||||
0x10000008, 0x10800000, 0x10802000, 0x00800008,
|
||||
0x10800000, 0x00002000, 0x00002008, 0x10802008,
|
||||
0x00802000, 0x00000008, 0x10000000, 0x00802000,
|
||||
0x10000000, 0x00802000, 0x00800000, 0x10002008,
|
||||
0x10002008, 0x10800008, 0x10800008, 0x00000008,
|
||||
0x00800008, 0x10000000, 0x10002000, 0x00800000,
|
||||
0x10802000, 0x00002008, 0x00802008, 0x10802000,
|
||||
0x00002008, 0x10000008, 0x10802008, 0x10800000,
|
||||
0x00802000, 0x00000000, 0x00000008, 0x10802008,
|
||||
0x00000000, 0x00802008, 0x10800000, 0x00002000,
|
||||
0x10000008, 0x10002000, 0x00002000, 0x00800008
|
||||
},
|
||||
/* Box S8 */ {
|
||||
0x40004100, 0x00004000, 0x00100000, 0x40104100,
|
||||
0x40000000, 0x40004100, 0x00000100, 0x40000000,
|
||||
0x00100100, 0x40100000, 0x40104100, 0x00104000,
|
||||
0x40104000, 0x00104100, 0x00004000, 0x00000100,
|
||||
0x40100000, 0x40000100, 0x40004000, 0x00004100,
|
||||
0x00104000, 0x00100100, 0x40100100, 0x40104000,
|
||||
0x00004100, 0x00000000, 0x00000000, 0x40100100,
|
||||
0x40000100, 0x40004000, 0x00104100, 0x00100000,
|
||||
0x00104100, 0x00100000, 0x40104000, 0x00004000,
|
||||
0x00000100, 0x40100100, 0x00004000, 0x00104100,
|
||||
0x40004000, 0x00000100, 0x40000100, 0x40100000,
|
||||
0x40100100, 0x40000000, 0x00100000, 0x40004100,
|
||||
0x00000000, 0x40104100, 0x00100100, 0x40000100,
|
||||
0x40100000, 0x40004000, 0x40004100, 0x00000000,
|
||||
0x40104100, 0x00104000, 0x00104000, 0x00004100,
|
||||
0x00004100, 0x00100100, 0x40000000, 0x40104000
|
||||
}
|
||||
};
|
||||
|
||||
static const HALF PC2[8][64] = {
|
||||
/* table 0 */ {
|
||||
0x00000000, 0x00001000, 0x04000000, 0x04001000,
|
||||
0x00100000, 0x00101000, 0x04100000, 0x04101000,
|
||||
0x00008000, 0x00009000, 0x04008000, 0x04009000,
|
||||
0x00108000, 0x00109000, 0x04108000, 0x04109000,
|
||||
0x00000004, 0x00001004, 0x04000004, 0x04001004,
|
||||
0x00100004, 0x00101004, 0x04100004, 0x04101004,
|
||||
0x00008004, 0x00009004, 0x04008004, 0x04009004,
|
||||
0x00108004, 0x00109004, 0x04108004, 0x04109004,
|
||||
0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
|
||||
0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
|
||||
0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
|
||||
0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
|
||||
0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
|
||||
0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
|
||||
0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
|
||||
0x08108004, 0x08109004, 0x0c108004, 0x0c109004
|
||||
},
|
||||
/* table 1 */ {
|
||||
0x00000000, 0x00002000, 0x80000000, 0x80002000,
|
||||
0x00000008, 0x00002008, 0x80000008, 0x80002008,
|
||||
0x00200000, 0x00202000, 0x80200000, 0x80202000,
|
||||
0x00200008, 0x00202008, 0x80200008, 0x80202008,
|
||||
0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
|
||||
0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
|
||||
0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
|
||||
0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
|
||||
0x00000400, 0x00002400, 0x80000400, 0x80002400,
|
||||
0x00000408, 0x00002408, 0x80000408, 0x80002408,
|
||||
0x00200400, 0x00202400, 0x80200400, 0x80202400,
|
||||
0x00200408, 0x00202408, 0x80200408, 0x80202408,
|
||||
0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
|
||||
0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
|
||||
0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
|
||||
0x20200408, 0x20202408, 0xa0200408, 0xa0202408
|
||||
},
|
||||
/* table 2 */ {
|
||||
0x00000000, 0x00004000, 0x00000020, 0x00004020,
|
||||
0x00080000, 0x00084000, 0x00080020, 0x00084020,
|
||||
0x00000800, 0x00004800, 0x00000820, 0x00004820,
|
||||
0x00080800, 0x00084800, 0x00080820, 0x00084820,
|
||||
0x00000010, 0x00004010, 0x00000030, 0x00004030,
|
||||
0x00080010, 0x00084010, 0x00080030, 0x00084030,
|
||||
0x00000810, 0x00004810, 0x00000830, 0x00004830,
|
||||
0x00080810, 0x00084810, 0x00080830, 0x00084830,
|
||||
0x00400000, 0x00404000, 0x00400020, 0x00404020,
|
||||
0x00480000, 0x00484000, 0x00480020, 0x00484020,
|
||||
0x00400800, 0x00404800, 0x00400820, 0x00404820,
|
||||
0x00480800, 0x00484800, 0x00480820, 0x00484820,
|
||||
0x00400010, 0x00404010, 0x00400030, 0x00404030,
|
||||
0x00480010, 0x00484010, 0x00480030, 0x00484030,
|
||||
0x00400810, 0x00404810, 0x00400830, 0x00404830,
|
||||
0x00480810, 0x00484810, 0x00480830, 0x00484830
|
||||
},
|
||||
/* table 3 */ {
|
||||
0x00000000, 0x40000000, 0x00000080, 0x40000080,
|
||||
0x00040000, 0x40040000, 0x00040080, 0x40040080,
|
||||
0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
|
||||
0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
|
||||
0x10000000, 0x50000000, 0x10000080, 0x50000080,
|
||||
0x10040000, 0x50040000, 0x10040080, 0x50040080,
|
||||
0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
|
||||
0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
|
||||
0x00800000, 0x40800000, 0x00800080, 0x40800080,
|
||||
0x00840000, 0x40840000, 0x00840080, 0x40840080,
|
||||
0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
|
||||
0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
|
||||
0x10800000, 0x50800000, 0x10800080, 0x50800080,
|
||||
0x10840000, 0x50840000, 0x10840080, 0x50840080,
|
||||
0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
|
||||
0x10840040, 0x50840040, 0x108400c0, 0x508400c0
|
||||
},
|
||||
/* table 4 */ {
|
||||
0x00000000, 0x00000008, 0x08000000, 0x08000008,
|
||||
0x00040000, 0x00040008, 0x08040000, 0x08040008,
|
||||
0x00002000, 0x00002008, 0x08002000, 0x08002008,
|
||||
0x00042000, 0x00042008, 0x08042000, 0x08042008,
|
||||
0x80000000, 0x80000008, 0x88000000, 0x88000008,
|
||||
0x80040000, 0x80040008, 0x88040000, 0x88040008,
|
||||
0x80002000, 0x80002008, 0x88002000, 0x88002008,
|
||||
0x80042000, 0x80042008, 0x88042000, 0x88042008,
|
||||
0x00080000, 0x00080008, 0x08080000, 0x08080008,
|
||||
0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
|
||||
0x00082000, 0x00082008, 0x08082000, 0x08082008,
|
||||
0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
|
||||
0x80080000, 0x80080008, 0x88080000, 0x88080008,
|
||||
0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
|
||||
0x80082000, 0x80082008, 0x88082000, 0x88082008,
|
||||
0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008
|
||||
},
|
||||
/* table 5 */ {
|
||||
0x00000000, 0x00400000, 0x00008000, 0x00408000,
|
||||
0x40000000, 0x40400000, 0x40008000, 0x40408000,
|
||||
0x00000020, 0x00400020, 0x00008020, 0x00408020,
|
||||
0x40000020, 0x40400020, 0x40008020, 0x40408020,
|
||||
0x00001000, 0x00401000, 0x00009000, 0x00409000,
|
||||
0x40001000, 0x40401000, 0x40009000, 0x40409000,
|
||||
0x00001020, 0x00401020, 0x00009020, 0x00409020,
|
||||
0x40001020, 0x40401020, 0x40009020, 0x40409020,
|
||||
0x00100000, 0x00500000, 0x00108000, 0x00508000,
|
||||
0x40100000, 0x40500000, 0x40108000, 0x40508000,
|
||||
0x00100020, 0x00500020, 0x00108020, 0x00508020,
|
||||
0x40100020, 0x40500020, 0x40108020, 0x40508020,
|
||||
0x00101000, 0x00501000, 0x00109000, 0x00509000,
|
||||
0x40101000, 0x40501000, 0x40109000, 0x40509000,
|
||||
0x00101020, 0x00501020, 0x00109020, 0x00509020,
|
||||
0x40101020, 0x40501020, 0x40109020, 0x40509020
|
||||
},
|
||||
/* table 6 */ {
|
||||
0x00000000, 0x00000040, 0x04000000, 0x04000040,
|
||||
0x00000800, 0x00000840, 0x04000800, 0x04000840,
|
||||
0x00800000, 0x00800040, 0x04800000, 0x04800040,
|
||||
0x00800800, 0x00800840, 0x04800800, 0x04800840,
|
||||
0x10000000, 0x10000040, 0x14000000, 0x14000040,
|
||||
0x10000800, 0x10000840, 0x14000800, 0x14000840,
|
||||
0x10800000, 0x10800040, 0x14800000, 0x14800040,
|
||||
0x10800800, 0x10800840, 0x14800800, 0x14800840,
|
||||
0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
|
||||
0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
|
||||
0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
|
||||
0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
|
||||
0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
|
||||
0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
|
||||
0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
|
||||
0x10800880, 0x108008c0, 0x14800880, 0x148008c0
|
||||
},
|
||||
/* table 7 */ {
|
||||
0x00000000, 0x00000010, 0x00000400, 0x00000410,
|
||||
0x00000004, 0x00000014, 0x00000404, 0x00000414,
|
||||
0x00004000, 0x00004010, 0x00004400, 0x00004410,
|
||||
0x00004004, 0x00004014, 0x00004404, 0x00004414,
|
||||
0x20000000, 0x20000010, 0x20000400, 0x20000410,
|
||||
0x20000004, 0x20000014, 0x20000404, 0x20000414,
|
||||
0x20004000, 0x20004010, 0x20004400, 0x20004410,
|
||||
0x20004004, 0x20004014, 0x20004404, 0x20004414,
|
||||
0x00200000, 0x00200010, 0x00200400, 0x00200410,
|
||||
0x00200004, 0x00200014, 0x00200404, 0x00200414,
|
||||
0x00204000, 0x00204010, 0x00204400, 0x00204410,
|
||||
0x00204004, 0x00204014, 0x00204404, 0x00204414,
|
||||
0x20200000, 0x20200010, 0x20200400, 0x20200410,
|
||||
0x20200004, 0x20200014, 0x20200404, 0x20200414,
|
||||
0x20204000, 0x20204010, 0x20204400, 0x20204410,
|
||||
0x20204004, 0x20204014, 0x20204404, 0x20204414
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The PC-1 Permutation
|
||||
* If we number the bits of the 8 bytes of key input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the PC-1 permutation,
|
||||
* C0 is
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43
|
||||
* D0 is
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 33 23 13 03
|
||||
* and these parity bits have been discarded:
|
||||
* 77 67 57 47 37 27 17 07
|
||||
*
|
||||
* We achieve this by flipping the input matrix about the diagonal from 70-07,
|
||||
* getting left =
|
||||
* 77 67 57 47 37 27 17 07 (these are the parity bits)
|
||||
* 76 66 56 46 36 26 16 06
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* right =
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* then byte swap right, ala htonl() on a little endian machine.
|
||||
* right =
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 71 67 57 47 37 27 11 07
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* then
|
||||
* c0 = right >> 4;
|
||||
* d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
*/
|
||||
|
||||
#define FLIP_RIGHT_DIAGONAL(word, temp) \
|
||||
temp = (word ^ (word >> 18)) & 0x00003333; \
|
||||
word ^= temp | (temp << 18); \
|
||||
temp = (word ^ (word >> 9)) & 0x00550055; \
|
||||
word ^= temp | (temp << 9);
|
||||
|
||||
#define BYTESWAP(word, temp) \
|
||||
word = (word >> 16) | (word << 16); \
|
||||
temp = 0x00ff00ff; \
|
||||
word = ((word & temp) << 8) | ((word >> 8) & temp);
|
||||
|
||||
#define PC1(left, right, c0, d0, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
FLIP_RIGHT_DIAGONAL(left, temp); \
|
||||
FLIP_RIGHT_DIAGONAL(right, temp); \
|
||||
BYTESWAP(right, temp); \
|
||||
c0 = right >> 4; \
|
||||
d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
|
||||
|
||||
#define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
|
||||
#define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
|
||||
|
||||
/*
|
||||
* setup key schedules from key
|
||||
*/
|
||||
|
||||
void
|
||||
DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF c0, d0;
|
||||
register HALF temp;
|
||||
int delta;
|
||||
unsigned int ls;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)key & 0x03) == 0) {
|
||||
left = HALFPTR(key)[0];
|
||||
right = HALFPTR(key)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
|
||||
((HALF)key[2] << 8) | key[3];
|
||||
right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
|
||||
((HALF)key[6] << 8) | key[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
PC1(left, right, c0, d0, temp);
|
||||
|
||||
if (direction == DES_ENCRYPT) {
|
||||
delta = 2 * (int)sizeof(HALF);
|
||||
} else {
|
||||
ks += 30;
|
||||
delta = (-2) * (int)sizeof(HALF);
|
||||
}
|
||||
|
||||
for (ls = 0x8103; ls; ls >>= 1) {
|
||||
if ( ls & 1 ) {
|
||||
c0 = LEFT_SHIFT_1( c0 );
|
||||
d0 = LEFT_SHIFT_1( d0 );
|
||||
} else {
|
||||
c0 = LEFT_SHIFT_2( c0 );
|
||||
d0 = LEFT_SHIFT_2( d0 );
|
||||
}
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define PC2LOOKUP(b,c) PC2[b][c]
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7) );
|
||||
left |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F) );
|
||||
right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
|
||||
#else
|
||||
#define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c))
|
||||
|
||||
left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) );
|
||||
left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) );
|
||||
left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C) );
|
||||
left |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0));
|
||||
|
||||
right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) );
|
||||
right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) );
|
||||
right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC) );
|
||||
right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
|
||||
#endif
|
||||
/* left contains key bits for S1 S3 S2 S4 */
|
||||
/* right contains key bits for S6 S8 S5 S7 */
|
||||
temp = (left << 16) /* S2 S4 XX XX */
|
||||
| (right >> 16); /* XX XX S6 S8 */
|
||||
ks[0] = temp;
|
||||
|
||||
temp = (left & 0xffff0000) /* S1 S3 XX XX */
|
||||
| (right & 0x0000ffff);/* XX XX S5 S7 */
|
||||
ks[1] = temp;
|
||||
|
||||
ks = (HALF*)((BYTE *)ks + delta);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The DES Initial Permutation
|
||||
* if we number the bits of the 8 bytes of input like this (in octal):
|
||||
* 00 01 02 03 04 05 06 07
|
||||
* 10 11 12 13 14 15 16 17
|
||||
* 20 21 22 23 24 25 26 27
|
||||
* 30 31 32 33 34 35 36 37
|
||||
* 40 41 42 43 44 45 46 47
|
||||
* 50 51 52 53 54 55 56 57
|
||||
* 60 61 62 63 64 65 66 67
|
||||
* 70 71 72 73 74 75 76 77
|
||||
* then after the initial permutation, they will be in this order.
|
||||
* 71 61 51 41 31 21 11 01
|
||||
* 73 63 53 43 33 23 13 03
|
||||
* 75 65 55 45 35 25 15 05
|
||||
* 77 67 57 47 37 27 17 07
|
||||
* 70 60 50 40 30 20 10 00
|
||||
* 72 62 52 42 32 22 12 02
|
||||
* 74 64 54 44 34 24 14 04
|
||||
* 76 66 56 46 36 26 16 06
|
||||
*
|
||||
* One way to do this is in two steps:
|
||||
* 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
|
||||
* 2. Rearrange the bytes (rows in the matrix above) with the following code.
|
||||
*
|
||||
* #define swapHiLo(word, temp) \
|
||||
* temp = (word ^ (word >> 24)) & 0x000000ff; \
|
||||
* word ^= temp | (temp << 24);
|
||||
*
|
||||
* right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
|
||||
* left ^= temp >> 8;
|
||||
* swapHiLo(left, temp);
|
||||
* swapHiLo(right,temp);
|
||||
*
|
||||
* However, the two steps can be combined, so that the rows are rearranged
|
||||
* while the matrix is being flipped, reducing the number of bit exchange
|
||||
* operations from 8 ot 5.
|
||||
*
|
||||
* Initial Permutation */
|
||||
#define IP(left, right, temp) \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1;
|
||||
|
||||
/* The Final (Inverse Initial) permutation is done by reversing the
|
||||
** steps of the Initital Permutation
|
||||
*/
|
||||
|
||||
#define FP(left, right, temp) \
|
||||
right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
|
||||
left ^= temp << 1; \
|
||||
right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
|
||||
left ^= temp >> 8; \
|
||||
right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
|
||||
left ^= temp >> 2; \
|
||||
right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
|
||||
left ^= temp << 16; \
|
||||
right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
|
||||
left ^= temp << 4;
|
||||
|
||||
void
|
||||
DES_Do1Block(HALF * ks, const BYTE * inbuf, BYTE * outbuf)
|
||||
{
|
||||
register HALF left, right;
|
||||
register HALF temp;
|
||||
|
||||
#if defined(_X86_)
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#else
|
||||
if (((ptrdiff_t)inbuf & 0x03) == 0) {
|
||||
left = HALFPTR(inbuf)[0];
|
||||
right = HALFPTR(inbuf)[1];
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
} else {
|
||||
left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
|
||||
((HALF)inbuf[2] << 8) | inbuf[3];
|
||||
right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
|
||||
((HALF)inbuf[6] << 8) | inbuf[7];
|
||||
}
|
||||
#endif
|
||||
|
||||
IP(left, right, temp);
|
||||
|
||||
/* shift the values left circularly 3 bits. */
|
||||
left = (left << 3) | (left >> 29);
|
||||
right = (right << 3) | (right >> 29);
|
||||
|
||||
#ifdef USE_INDEXING
|
||||
#define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]
|
||||
#else
|
||||
#define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))
|
||||
#endif
|
||||
#define ROUND(out, in, r) \
|
||||
temp = in ^ ks[2*r]; \
|
||||
out ^= KSLOOKUP( 1, 24 ); \
|
||||
out ^= KSLOOKUP( 3, 16 ); \
|
||||
out ^= KSLOOKUP( 5, 8 ); \
|
||||
out ^= KSLOOKUP( 7, 0 ); \
|
||||
temp = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \
|
||||
out ^= KSLOOKUP( 0, 24 ); \
|
||||
out ^= KSLOOKUP( 2, 16 ); \
|
||||
out ^= KSLOOKUP( 4, 8 ); \
|
||||
out ^= KSLOOKUP( 6, 0 );
|
||||
|
||||
/* Do the 16 Feistel rounds */
|
||||
ROUND(left, right, 0)
|
||||
ROUND(right, left, 1)
|
||||
ROUND(left, right, 2)
|
||||
ROUND(right, left, 3)
|
||||
ROUND(left, right, 4)
|
||||
ROUND(right, left, 5)
|
||||
ROUND(left, right, 6)
|
||||
ROUND(right, left, 7)
|
||||
ROUND(left, right, 8)
|
||||
ROUND(right, left, 9)
|
||||
ROUND(left, right, 10)
|
||||
ROUND(right, left, 11)
|
||||
ROUND(left, right, 12)
|
||||
ROUND(right, left, 13)
|
||||
ROUND(left, right, 14)
|
||||
ROUND(right, left, 15)
|
||||
|
||||
/* now shift circularly right 3 bits to undo the shifting done
|
||||
** above. switch left and right here.
|
||||
*/
|
||||
temp = (left >> 3) | (left << 29);
|
||||
left = (right >> 3) | (right << 29);
|
||||
right = temp;
|
||||
|
||||
FP(left, right, temp);
|
||||
|
||||
#if defined(_X86_)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
#else
|
||||
if (((ptrdiff_t)outbuf & 0x03) == 0) {
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
BYTESWAP(left, temp);
|
||||
BYTESWAP(right, temp);
|
||||
#endif
|
||||
HALFPTR(outbuf)[0] = left;
|
||||
HALFPTR(outbuf)[1] = right;
|
||||
} else {
|
||||
outbuf[0] = (BYTE)(left >> 24);
|
||||
outbuf[1] = (BYTE)(left >> 16);
|
||||
outbuf[2] = (BYTE)(left >> 8);
|
||||
outbuf[3] = (BYTE)(left );
|
||||
|
||||
outbuf[4] = (BYTE)(right >> 24);
|
||||
outbuf[5] = (BYTE)(right >> 16);
|
||||
outbuf[6] = (BYTE)(right >> 8);
|
||||
outbuf[7] = (BYTE)(right );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Ackowledgements:
|
||||
** Two ideas used in this implementation were shown to me by Dennis Ferguson
|
||||
** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:
|
||||
** 1. The method of computing the Initial and Final permutations.
|
||||
** 2. Circularly rotating the SP tables and the initial values of left and
|
||||
** right to reduce the number of shifts required during the 16 rounds.
|
||||
*/
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* des.h
|
||||
*
|
||||
* header file for DES-150 library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _DES_H_
|
||||
#define _DES_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define HALFPTR(x) ((HALF *)(x))
|
||||
#define SHORTPTR(x) ((unsigned short *)(x))
|
||||
#define BYTEPTR(x) ((BYTE *)(x))
|
||||
|
||||
typedef enum {
|
||||
DES_ENCRYPT = 0x5555,
|
||||
DES_DECRYPT = 0xAAAA
|
||||
} DESDirection;
|
||||
|
||||
typedef void DESFunc(struct DESContextStr *cx, BYTE *out, const BYTE *in,
|
||||
unsigned int len);
|
||||
|
||||
struct DESContextStr {
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
HALF ks0 [32];
|
||||
HALF ks1 [32];
|
||||
HALF ks2 [32];
|
||||
HALF iv [2];
|
||||
DESDirection direction;
|
||||
DESFunc *worker;
|
||||
};
|
||||
|
||||
void DES_MakeSchedule( HALF * ks, const BYTE * key, DESDirection direction);
|
||||
void DES_Do1Block( HALF * ks, const BYTE * inbuf, BYTE * outbuf);
|
||||
|
||||
#endif
|
||||
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* desblapi.c
|
||||
*
|
||||
* core source file for DES-150 library
|
||||
* Implement DES Modes of Operation and Triple-DES.
|
||||
* Adapt DES-150 to blapi API.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "des.h"
|
||||
#include <stddef.h>
|
||||
#include "secerr.h"
|
||||
|
||||
#if defined(_X86_)
|
||||
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
|
||||
#define COPY8B(to, from, ptr) \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1];
|
||||
#elif defined(USE_MEMCPY)
|
||||
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
|
||||
#else
|
||||
#define COPY8B(to, from, ptr) \
|
||||
if (((ptrdiff_t)(ptr) & 0x3) == 0) { \
|
||||
HALFPTR(to)[0] = HALFPTR(from)[0]; \
|
||||
HALFPTR(to)[1] = HALFPTR(from)[1]; \
|
||||
} else if (((ptrdiff_t)(ptr) & 0x1) == 0) { \
|
||||
SHORTPTR(to)[0] = SHORTPTR(from)[0]; \
|
||||
SHORTPTR(to)[1] = SHORTPTR(from)[1]; \
|
||||
SHORTPTR(to)[2] = SHORTPTR(from)[2]; \
|
||||
SHORTPTR(to)[3] = SHORTPTR(from)[3]; \
|
||||
} else { \
|
||||
BYTEPTR(to)[0] = BYTEPTR(from)[0]; \
|
||||
BYTEPTR(to)[1] = BYTEPTR(from)[1]; \
|
||||
BYTEPTR(to)[2] = BYTEPTR(from)[2]; \
|
||||
BYTEPTR(to)[3] = BYTEPTR(from)[3]; \
|
||||
BYTEPTR(to)[4] = BYTEPTR(from)[4]; \
|
||||
BYTEPTR(to)[5] = BYTEPTR(from)[5]; \
|
||||
BYTEPTR(to)[6] = BYTEPTR(from)[6]; \
|
||||
BYTEPTR(to)[7] = BYTEPTR(from)[7]; \
|
||||
}
|
||||
#endif
|
||||
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
|
||||
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
|
||||
|
||||
static void
|
||||
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
while (len) {
|
||||
DES_Do1Block(cx->ks0, in, out);
|
||||
len -= 8;
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks1, out, out);
|
||||
DES_Do1Block(cx->ks2, out, out);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend = in + len;
|
||||
HALF vec[2];
|
||||
|
||||
while (in != bufend) {
|
||||
COPY8BTOHALF(vec, in);
|
||||
in += 8;
|
||||
vec[0] ^= cx->iv[0];
|
||||
vec[1] ^= cx->iv[1];
|
||||
DES_Do1Block( cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
DES_Do1Block( cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
|
||||
COPY8BFROMHALF(out, cx->iv);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
|
||||
{
|
||||
const BYTE * bufend;
|
||||
HALF oldciphertext[2];
|
||||
HALF plaintext [2];
|
||||
|
||||
for (bufend = in + len; in != bufend; ) {
|
||||
oldciphertext[0] = cx->iv[0];
|
||||
oldciphertext[1] = cx->iv[1];
|
||||
COPY8BTOHALF(cx->iv, in);
|
||||
in += 8;
|
||||
DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
|
||||
plaintext[0] ^= oldciphertext[0];
|
||||
plaintext[1] ^= oldciphertext[1];
|
||||
COPY8BFROMHALF(out, plaintext);
|
||||
out += 8;
|
||||
}
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_AllocateContext(void)
|
||||
{
|
||||
return PORT_ZNew(DESContext);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *iv, int mode, unsigned int encrypt,
|
||||
unsigned int unused)
|
||||
{
|
||||
DESDirection opposite;
|
||||
if (!cx) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
|
||||
opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
|
||||
switch (mode) {
|
||||
case NSS_DES: /* DES ECB */
|
||||
DES_MakeSchedule( cx->ks0, key, cx->direction);
|
||||
cx->worker = &DES_ECB;
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3: /* DES EDE ECB */
|
||||
cx->worker = &DES_EDE3_ECB;
|
||||
if (encrypt) {
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSS_DES_CBC: /* DES CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
break;
|
||||
|
||||
case NSS_DES_EDE3_CBC: /* DES EDE CBC */
|
||||
COPY8BTOHALF(cx->iv, iv);
|
||||
if (encrypt) {
|
||||
cx->worker = &DES_EDE3CBCEn;
|
||||
DES_MakeSchedule(cx->ks0, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
|
||||
} else {
|
||||
cx->worker = &DES_EDE3CBCDe;
|
||||
DES_MakeSchedule(cx->ks2, key, cx->direction);
|
||||
DES_MakeSchedule(cx->ks1, key + 8, opposite);
|
||||
DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
DESContext *
|
||||
DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt)
|
||||
{
|
||||
DESContext *cx = PORT_ZNew(DESContext);
|
||||
SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
PORT_ZFree(cx, sizeof *cx);
|
||||
cx = NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
DES_DestroyContext(DESContext *cx, PRBool freeit)
|
||||
{
|
||||
if (cx) {
|
||||
memset(cx, 0, sizeof *cx);
|
||||
if (freeit)
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_ENCRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
|
||||
unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
|
||||
{
|
||||
|
||||
if (inLen < 0 || (inLen % 8) != 0 || maxOutLen < inLen || !cx ||
|
||||
cx->direction != DES_DECRYPT) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
cx->worker(cx, out, in, inLen);
|
||||
if (outLen)
|
||||
*outLen = inLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Diffie-Hellman parameter generation, key generation, and secret derivation.
|
||||
* KEA secret generation and verification.
|
||||
*
|
||||
* $Id: dh.c,v 1.7 2004-04-25 15:03:08 gerv%gerv.net Exp $
|
||||
*/
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secitem.h"
|
||||
#include "mpi.h"
|
||||
#include "mpprime.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
#define DH_SECRET_KEY_LEN 20
|
||||
#define KEA_DERIVED_SECRET_LEN 128
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams **params)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHParams *dhparams;
|
||||
unsigned char *pb = NULL;
|
||||
unsigned char *ab = NULL;
|
||||
unsigned long counter = 0;
|
||||
mp_int p, q, a, h, psub1, test;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || primeLen < 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams = (DHParams *)PORT_ArenaZAlloc(arena, sizeof(DHParams));
|
||||
if (!dhparams) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
dhparams->arena = arena;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&a) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&psub1) = 0;
|
||||
MP_DIGITS(&test) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&a) );
|
||||
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. */
|
||||
pb = PORT_Alloc(primeLen);
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(pb, primeLen) );
|
||||
pb[0] |= 0x80; /* set high-order bit */
|
||||
pb[primeLen-1] |= 0x01; /* set low-order bit */
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&p, pb, primeLen) );
|
||||
CHECK_MPI_OK( mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter) );
|
||||
/* construct Sophie-Germain prime q = (p-1)/2. */
|
||||
CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
|
||||
CHECK_MPI_OK( mp_div_2(&psub1, &q) );
|
||||
/* construct a generator from the prime. */
|
||||
ab = PORT_Alloc(primeLen);
|
||||
/* generate a candidate number a in p's field */
|
||||
CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(ab, primeLen) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&a, ab, primeLen) );
|
||||
/* force a < p (note that quot(a/p) <= 1) */
|
||||
if ( mp_cmp(&a, &p) > 0 )
|
||||
CHECK_MPI_OK( mp_sub(&a, &p, &a) );
|
||||
do {
|
||||
/* check that a is in the range [2..p-1] */
|
||||
if ( mp_cmp_d(&a, 2) < 0 || mp_cmp(&a, &psub1) >= 0) {
|
||||
/* a is outside of the allowed range. Set a=3 and keep going. */
|
||||
mp_set(&a, 3);
|
||||
}
|
||||
/* if a**q mod p != 1 then a is a generator */
|
||||
CHECK_MPI_OK( mp_exptmod(&a, &q, &p, &test) );
|
||||
if ( mp_cmp_d(&test, 1) != 0 )
|
||||
break;
|
||||
/* increment the candidate and try again. */
|
||||
CHECK_MPI_OK( mp_add_d(&a, 1, &a) );
|
||||
} while (PR_TRUE);
|
||||
MPINT_TO_SECITEM(&p, &dhparams->prime, arena);
|
||||
MPINT_TO_SECITEM(&a, &dhparams->base, arena);
|
||||
*params = dhparams;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&a);
|
||||
mp_clear(&h);
|
||||
mp_clear(&psub1);
|
||||
mp_clear(&test);
|
||||
if (pb) PORT_ZFree(pb, primeLen);
|
||||
if (ab) PORT_ZFree(ab, primeLen);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_NewKey(DHParams *params, DHPrivateKey **privKey)
|
||||
{
|
||||
PRArenaPool *arena;
|
||||
DHPrivateKey *key;
|
||||
mp_int g, xa, p, Ya;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DHPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DHPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->arena = arena;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&xa) = 0;
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Ya) = 0;
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&xa) );
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Ya) );
|
||||
/* Set private key's p */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->prime, ¶ms->prime) );
|
||||
SECITEM_TO_MPINT(key->prime, &p);
|
||||
/* Set private key's g */
|
||||
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, ¶ms->base) );
|
||||
SECITEM_TO_MPINT(key->base, &g);
|
||||
/* Generate private key xa */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DH_SECRET_KEY_LEN);
|
||||
RNG_GenerateGlobalRandomBytes(key->privateValue.data,
|
||||
key->privateValue.len);
|
||||
SECITEM_TO_MPINT( key->privateValue, &xa );
|
||||
/* xa < p */
|
||||
CHECK_MPI_OK( mp_mod(&xa, &p, &xa) );
|
||||
/* Compute public key Ya = g ** xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &xa, &p, &Ya) );
|
||||
MPINT_TO_SECITEM(&Ya, &key->publicValue, key->arena);
|
||||
*privKey = key;
|
||||
cleanup:
|
||||
mp_clear(&g);
|
||||
mp_clear(&xa);
|
||||
mp_clear(&p);
|
||||
mp_clear(&Ya);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv)
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_Derive(SECItem *publicValue,
|
||||
SECItem *prime,
|
||||
SECItem *privateValue,
|
||||
SECItem *derivedSecret,
|
||||
unsigned int maxOutBytes)
|
||||
{
|
||||
mp_int p, Xa, Yb, ZZ;
|
||||
mp_err err = MP_OKAY;
|
||||
unsigned int len = 0, nb;
|
||||
unsigned char *secret = NULL;
|
||||
if (!publicValue || !prime || !privateValue || !derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Xa) = 0;
|
||||
MP_DIGITS(&Yb) = 0;
|
||||
MP_DIGITS(&ZZ) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Xa) );
|
||||
CHECK_MPI_OK( mp_init(&Yb) );
|
||||
CHECK_MPI_OK( mp_init(&ZZ) );
|
||||
SECITEM_TO_MPINT(*publicValue, &Yb);
|
||||
SECITEM_TO_MPINT(*privateValue, &Xa);
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
/* ZZ = (Yb)**Xa mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Yb, &Xa, &p, &ZZ) );
|
||||
/* number of bytes in the derived secret */
|
||||
len = mp_unsigned_octet_size(&ZZ);
|
||||
/* allocate a buffer which can hold the entire derived secret. */
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the derived secret */
|
||||
err = mp_to_unsigned_octets(&ZZ, secret, len);
|
||||
if (err >= 0) err = MP_OKAY;
|
||||
/* Take minimum of bytes requested and bytes in derived secret,
|
||||
** if maxOutBytes is 0 take all of the bytes from the derived secret.
|
||||
*/
|
||||
if (maxOutBytes > 0)
|
||||
nb = PR_MIN(len, maxOutBytes);
|
||||
else
|
||||
nb = len;
|
||||
SECITEM_AllocItem(NULL, derivedSecret, nb);
|
||||
memcpy(derivedSecret->data, secret, nb);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Xa);
|
||||
mp_clear(&Yb);
|
||||
mp_clear(&ZZ);
|
||||
if (secret) {
|
||||
/* free the buffer allocated for the full secret. */
|
||||
PORT_ZFree(secret, len);
|
||||
}
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
if (derivedSecret->data)
|
||||
PORT_ZFree(derivedSecret->data, derivedSecret->len);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
KEA_Derive(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret)
|
||||
{
|
||||
mp_int p, Y, R, r, x, t, u, w;
|
||||
mp_err err;
|
||||
unsigned char *secret = NULL;
|
||||
unsigned int len = 0, offset;
|
||||
if (!prime || !public1 || !public2 || !private1 || !private2 ||
|
||||
!derivedSecret) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
memset(derivedSecret, 0, sizeof *derivedSecret);
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&Y) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&t) = 0;
|
||||
MP_DIGITS(&u) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&Y) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&t) );
|
||||
CHECK_MPI_OK( mp_init(&u) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*public1, &Y);
|
||||
SECITEM_TO_MPINT(*public2, &R);
|
||||
SECITEM_TO_MPINT(*private1, &r);
|
||||
SECITEM_TO_MPINT(*private2, &x);
|
||||
/* t = DH(Y, r, p) = Y ** r mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&Y, &r, &p, &t) );
|
||||
/* u = DH(R, x, p) = R ** x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&R, &x, &p, &u) );
|
||||
/* w = (t + u) mod p */
|
||||
CHECK_MPI_OK( mp_addmod(&t, &u, &p, &w) );
|
||||
/* allocate a buffer for the full derived secret */
|
||||
len = mp_unsigned_octet_size(&w);
|
||||
secret = PORT_Alloc(len);
|
||||
/* grab the secret */
|
||||
err = mp_to_unsigned_octets(&w, secret, len);
|
||||
if (err > 0) err = MP_OKAY;
|
||||
/* allocate output buffer */
|
||||
SECITEM_AllocItem(NULL, derivedSecret, KEA_DERIVED_SECRET_LEN);
|
||||
memset(derivedSecret->data, 0, derivedSecret->len);
|
||||
/* copy in the 128 lsb of the secret */
|
||||
if (len >= KEA_DERIVED_SECRET_LEN) {
|
||||
memcpy(derivedSecret->data, secret + (len - KEA_DERIVED_SECRET_LEN),
|
||||
KEA_DERIVED_SECRET_LEN);
|
||||
} else {
|
||||
offset = KEA_DERIVED_SECRET_LEN - len;
|
||||
memcpy(derivedSecret->data + offset, secret, len);
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&Y);
|
||||
mp_clear(&R);
|
||||
mp_clear(&r);
|
||||
mp_clear(&x);
|
||||
mp_clear(&t);
|
||||
mp_clear(&u);
|
||||
mp_clear(&w);
|
||||
if (secret)
|
||||
PORT_ZFree(secret, len);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
PRBool
|
||||
KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime)
|
||||
{
|
||||
mp_int p, q, y, r;
|
||||
mp_err err;
|
||||
int cmp = 1; /* default is false */
|
||||
if (!Y || !prime || !subPrime) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
SECITEM_TO_MPINT(*prime, &p);
|
||||
SECITEM_TO_MPINT(*subPrime, &q);
|
||||
SECITEM_TO_MPINT(*Y, &y);
|
||||
/* compute r = y**q mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &q, &p, &r) );
|
||||
/* compare to 1 */
|
||||
cmp = mp_cmp_d(&r, 1);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return PR_FALSE;
|
||||
}
|
||||
return (cmp == 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
@@ -1,450 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: dsa.c,v 1.18 2005-10-12 00:48:25 wtchang%redhat.com Exp $ */
|
||||
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prinit.h"
|
||||
#include "blapi.h"
|
||||
#include "nssilock.h"
|
||||
#include "secitem.h"
|
||||
#include "blapi.h"
|
||||
#include "mpi.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
/* XXX to be replaced by define in blapit.h */
|
||||
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
/* DSA-specific random number function defined in prng_fips1861.c. */
|
||||
extern SECStatus
|
||||
DSA_GenerateGlobalRandomBytes(void *dest, size_t len, const unsigned char *q);
|
||||
|
||||
static void translate_mpi_error(mp_err err)
|
||||
{
|
||||
MP_TO_SEC_ERROR(err);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
||||
const unsigned char *xb)
|
||||
{
|
||||
mp_int p, g;
|
||||
mp_int x, y;
|
||||
mp_err err;
|
||||
PRArenaPool *arena;
|
||||
DSAPrivateKey *key;
|
||||
/* Check args. */
|
||||
if (!params || !privKey) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize an arena for the DSA key. */
|
||||
arena = PORT_NewArena(NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
return SECFailure;
|
||||
}
|
||||
key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey));
|
||||
if (!key) {
|
||||
PORT_SetError(SEC_ERROR_NO_MEMORY);
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return SECFailure;
|
||||
}
|
||||
key->params.arena = arena;
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
/* Copy over the PQG params */
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
|
||||
¶ms->prime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
|
||||
¶ms->subPrime) );
|
||||
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) );
|
||||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN);
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
MPINT_TO_SECITEM(&y, &key->publicValue, arena);
|
||||
*privKey = key;
|
||||
key = NULL;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&y);
|
||||
if (key)
|
||||
PORT_FreeArena(key->params.arena, PR_TRUE);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
** "params" is a pointer to the PQG parameters for the domain
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
int retries = 10;
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
do {
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Disallow values of 0 and 1 for x. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) {
|
||||
if (seed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good && seed[i] > 1) {
|
||||
good = PR_TRUE;
|
||||
}
|
||||
} while (!good && --retries > 0);
|
||||
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
|
||||
SECStatus
|
||||
DSA_NewKeyFromSeed(const PQGParams *params,
|
||||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
|
||||
const unsigned char *kb)
|
||||
{
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int x, k; /* private key & pseudo-random integer */
|
||||
mp_int r, s; /* tuple (r, s) is signature) */
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len < DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&x) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&x) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
/*
|
||||
** Convert stored PQG and private key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->privateValue, &x);
|
||||
OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 1
|
||||
**
|
||||
** r = (g**k mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */
|
||||
CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 5, Step 2
|
||||
**
|
||||
** s = (k**-1 * (SHA1(M) + x*r)) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
|
||||
CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
|
||||
CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
|
||||
CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */
|
||||
/*
|
||||
** verify r != 0 and s != 0
|
||||
** mentioned as optional in FIPS 186-1.
|
||||
*/
|
||||
if (mp_cmp_z(&r) == 0 || mp_cmp_z(&s) == 0) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
** Step 4
|
||||
**
|
||||
** Signature is tuple (r, s)
|
||||
*/
|
||||
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
|
||||
DSA_SUBPRIME_LEN);
|
||||
if (err < 0) goto cleanup;
|
||||
err = MP_OKAY;
|
||||
signature->len = DSA_SIGNATURE_LEN;
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&x);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&s);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 40 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
** On output, signature->len == size of signature in buffer.
|
||||
** Uses a random seed.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
||||
{
|
||||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = DSA_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
/* Disallow a value of 0 for k. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN; i++) {
|
||||
if (kSeed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
rv = SECFailure;
|
||||
continue;
|
||||
}
|
||||
rv = dsa_SignDigest(key, signature, digest, kSeed);
|
||||
} while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM &&
|
||||
--retries > 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* For FIPS compliance testing. Seed must be exactly 20 bytes. */
|
||||
SECStatus
|
||||
DSA_SignDigestWithSeed(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_SignDigest(key, signature, digest, seed);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* signature is caller-supplied buffer of at least 20 bytes.
|
||||
** On input, signature->len == size of buffer to hold signature.
|
||||
** digest->len == size of digest.
|
||||
*/
|
||||
SECStatus
|
||||
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
|
||||
const SECItem *digest)
|
||||
{
|
||||
/* FIPS-compliance dictates that digest is a SHA1 hash. */
|
||||
mp_int p, q, g; /* PQG parameters */
|
||||
mp_int r_, s_; /* tuple (r', s') is received signature) */
|
||||
mp_int u1, u2, v, w; /* intermediate values used in verification */
|
||||
mp_int y; /* public key */
|
||||
mp_err err;
|
||||
SECStatus verified = SECFailure;
|
||||
|
||||
/* Check args. */
|
||||
if (!key || !signature || !digest ||
|
||||
(signature->len != DSA_SIGNATURE_LEN) ||
|
||||
(digest->len != SHA1_LENGTH)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
/* Initialize MPI integers. */
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&y) = 0;
|
||||
MP_DIGITS(&r_) = 0;
|
||||
MP_DIGITS(&s_) = 0;
|
||||
MP_DIGITS(&u1) = 0;
|
||||
MP_DIGITS(&u2) = 0;
|
||||
MP_DIGITS(&v) = 0;
|
||||
MP_DIGITS(&w) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&y) );
|
||||
CHECK_MPI_OK( mp_init(&r_) );
|
||||
CHECK_MPI_OK( mp_init(&s_) );
|
||||
CHECK_MPI_OK( mp_init(&u1) );
|
||||
CHECK_MPI_OK( mp_init(&u2) );
|
||||
CHECK_MPI_OK( mp_init(&v) );
|
||||
CHECK_MPI_OK( mp_init(&w) );
|
||||
/*
|
||||
** Convert stored PQG and public key into MPI integers.
|
||||
*/
|
||||
SECITEM_TO_MPINT(key->params.prime, &p);
|
||||
SECITEM_TO_MPINT(key->params.subPrime, &q);
|
||||
SECITEM_TO_MPINT(key->params.base, &g);
|
||||
SECITEM_TO_MPINT(key->publicValue, &y);
|
||||
/*
|
||||
** Convert received signature (r', s') into MPI integers.
|
||||
*/
|
||||
OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
|
||||
OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
|
||||
/*
|
||||
** Verify that 0 < r' < q and 0 < s' < q
|
||||
*/
|
||||
if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
|
||||
mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
|
||||
/* err is zero here. */
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
goto cleanup; /* will return verified == SECFailure */
|
||||
}
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 1
|
||||
**
|
||||
** w = (s')**-1 mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 2
|
||||
**
|
||||
** u1 = ((SHA1(M')) * w) mod q
|
||||
*/
|
||||
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
|
||||
CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 3
|
||||
**
|
||||
** u2 = ((r') * w) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
|
||||
/*
|
||||
** FIPS 186-1, Section 6, Step 4
|
||||
**
|
||||
** v = ((g**u1 * y**u2) mod p) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
|
||||
CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */
|
||||
CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */
|
||||
/*
|
||||
** Verification: v == r'
|
||||
*/
|
||||
if (mp_cmp(&v, &r_)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
verified = SECFailure; /* Signature failed to verify. */
|
||||
} else {
|
||||
verified = SECSuccess; /* Signature verified. */
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&y);
|
||||
mp_clear(&r_);
|
||||
mp_clear(&s_);
|
||||
mp_clear(&u1);
|
||||
mp_clear(&u2);
|
||||
mp_clear(&v);
|
||||
mp_clear(&w);
|
||||
if (err) {
|
||||
translate_mpi_error(err);
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Elliptic Curve Cryptography library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec_h_
|
||||
#define __ec_h_
|
||||
|
||||
#define EC_DEBUG 0
|
||||
#define EC_POINT_FORM_COMPRESSED_Y0 0x02
|
||||
#define EC_POINT_FORM_COMPRESSED_Y1 0x03
|
||||
#define EC_POINT_FORM_UNCOMPRESSED 0x04
|
||||
#define EC_POINT_FORM_HYBRID_Y0 0x06
|
||||
#define EC_POINT_FORM_HYBRID_Y1 0x07
|
||||
|
||||
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
|
||||
#define SECG_CURVE_OID_TOTAL_LEN 7
|
||||
|
||||
#endif /* __ec_h_ */
|
||||
@@ -1,230 +0,0 @@
|
||||
#
|
||||
# Makefile for elliptic curve library
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the elliptic curve math library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Sun Microsystems, Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2003
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Douglas Stebila <douglas@stebila.ca>
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
include ../mpi/target.mk
|
||||
|
||||
##
|
||||
## Define platform-dependent variables for use of floating-point code.
|
||||
##
|
||||
ifeq ($(TARGET),v9SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8plusSOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),v8SOLARIS)
|
||||
ECL_USE_FP=1
|
||||
else
|
||||
ifeq ($(TARGET),x86LINUX)
|
||||
ECL_USE_FP=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
##
|
||||
## Add to definition of CFLAGS depending on use of floating-point code.
|
||||
##
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
CFLAGS+= -DECL_USE_FP
|
||||
endif
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=-L../mpi -lmpi -lm#-lmalloc#-lefence
|
||||
|
||||
##
|
||||
## Define INCLUDES to include any include directories you need to
|
||||
## compile with.
|
||||
##
|
||||
INCLUDES=-I../mpi
|
||||
CFLAGS+= $(INCLUDES) $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## Define LIBOBJS to be the object files that will be created during
|
||||
## the build process.
|
||||
##
|
||||
LIBOBJS = ecl.o ecl_curve.o ecl_mult.o ecl_gf.o \
|
||||
ec2_aff.o ec2_mont.o ec2_proj.o \
|
||||
ec2_163.o ec2_193.o ec2_233.o \
|
||||
ecp_aff.o ecp_jac.o ecp_mont.o \
|
||||
ec_naf.o ecp_jm.o \
|
||||
ecp_192.o ecp_224.o ecp_256.o ecp_384.o ecp_521.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
LIBOBJS+= ecp_fp160.o ecp_fp192.o ecp_fp224.o ecp_fp.o
|
||||
endif
|
||||
|
||||
## The headers contained in this library.
|
||||
LIBHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
APPHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h
|
||||
ifeq ($(ECL_GFP_ASSEMBLY_FP),1)
|
||||
LIBHDRS += ecp_fp.h
|
||||
APPHDRS += ecp_fp.h
|
||||
endif
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libecl.a - elliptic curve library"
|
||||
@ echo "tests - build command line tests"
|
||||
@ echo "test - run command line tests"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
ecl.o: ecl.c $(LIBHDRS)
|
||||
ecl_curve.o: ecl_curve.c $(LIBHDRS)
|
||||
ecl_mult.o: ecl_mult.c $(LIBHDRS)
|
||||
ecl_gf.o: ecl_gf.c $(LIBHDRS)
|
||||
ec2_aff.o: ec2_aff.c $(LIBHDRS)
|
||||
ec2_mont.o: ec2_mont.c $(LIBHDRS)
|
||||
ec2_proj.o: ec2_proj.c $(LIBHDRS)
|
||||
ec2_163.o: ec2_163.c $(LIBHDRS)
|
||||
ec2_193.o: ec2_193.c $(LIBHDRS)
|
||||
ec2_233.o: ec2_233.c $(LIBHDRS)
|
||||
ecp_aff.o: ecp_aff.c $(LIBHDRS)
|
||||
ecp_jac.o: ecp_jac.c $(LIBHDRS)
|
||||
ecp_jm.o: ecp_jm.c $(LIBHDRS)
|
||||
ecp_mont.o: ecp_mont.c $(LIBHDRS)
|
||||
ecp_192.o: ecp_192.c $(LIBHDRS)
|
||||
ecp_224.o: ecp_224.c $(LIBHDRS)
|
||||
ecp_256.o: ecp_256.c $(LIBHDRS)
|
||||
ecp_384.o: ecp_384.c $(LIBHDRS)
|
||||
ecp_521.o: ecp_521.c $(LIBHDRS)
|
||||
ecp_fp.o: ecp_fp.c $(LIBHDRS)
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ecp_fp160.o: ecp_fp160.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp192.o: ecp_fp192.c ecp_fpinc.c $(LIBHDRS)
|
||||
ecp_fp224.o: ecp_fp224.c ecp_fpinc.c $(LIBHDRS)
|
||||
endif
|
||||
|
||||
libecl.a: $(LIBOBJS)
|
||||
ar -cvr libecl.a $(LIBOBJS)
|
||||
$(RANLIB) libecl.a
|
||||
|
||||
lib libs: libecl.a
|
||||
|
||||
ecl.i: ecl.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ECLTESTOBJS = ec2_test.o ecp_test.o ec_naft.o
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
ECLTESTOBJS+= ecp_fpt.o
|
||||
endif
|
||||
ECLTESTS = $(ECLTESTOBJS:.o=)
|
||||
|
||||
$(ECLTESTOBJS): %.o: tests/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDES)
|
||||
|
||||
$(ECLTESTS): %: %.o libecl.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
tests: ec2_test ecp_test ec_naft ecp_fpt
|
||||
else
|
||||
tests: ec2_test ecp_test ec_naft
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
ifeq ($(ECL_USE_FP),1)
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec2_test
|
||||
./ec_naft
|
||||
./ecp_fpt
|
||||
else
|
||||
test: tests
|
||||
./ecp_test
|
||||
./ec_naft
|
||||
./ec2_test
|
||||
endif
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f $(ECLTESTS)
|
||||
|
||||
clobber: clean
|
||||
|
||||
# END
|
||||
@@ -1,330 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
|
||||
HEADER FILES
|
||||
============
|
||||
|
||||
ecl-exp.h - Exports data structures and curve names. For use by code
|
||||
that does not have access to mp_ints.
|
||||
|
||||
ecl-curve.h - Provides hex encodings (in the form of ECCurveParams
|
||||
structs) of standardizes elliptic curve domain parameters and mappings
|
||||
from ECCurveName to ECCurveParams. For use by code that does not have
|
||||
access to mp_ints.
|
||||
|
||||
ecl.h - Interface to constructors for curve parameters and group object,
|
||||
and point multiplication operations. Used by higher level algorithms
|
||||
(like ECDH and ECDSA) to actually perform elliptic curve cryptography.
|
||||
|
||||
ecl-priv.h - Data structures and functions for internal use within the
|
||||
library.
|
||||
|
||||
ec2.h - Internal header file that contains all functions for point
|
||||
arithmetic over binary polynomial fields.
|
||||
|
||||
ecp.h - Internal header file that contains all functions for point
|
||||
arithmetic over prime fields.
|
||||
|
||||
DATA STRUCTURES AND TYPES
|
||||
=========================
|
||||
|
||||
ECCurveName (from ecl-exp.h) - Opaque name for standardized elliptic
|
||||
curve domain parameters.
|
||||
|
||||
ECCurveParams (from ecl-exp.h) - Provides hexadecimal encoding
|
||||
of elliptic curve domain parameters. Can be generated by a user
|
||||
and passed to ECGroup_fromHex or can be generated from a name by
|
||||
EC_GetNamedCurveParams. ecl-curve.h contains ECCurveParams structs for
|
||||
the standardized curves defined by ECCurveName.
|
||||
|
||||
ECGroup (from ecl.h and ecl-priv.h) - Opaque data structure that
|
||||
represents a group of elliptic curve points for a particular set of
|
||||
elliptic curve domain parameters. Contains all domain parameters (curve
|
||||
a and b, field, base point) as well as pointers to the functions that
|
||||
should be used for point arithmetic and the underlying field GFMethod.
|
||||
Generated by either ECGroup_fromHex or ECGroup_fromName.
|
||||
|
||||
GFMethod (from ecl-priv.h) - Represents a field underlying a set of
|
||||
elliptic curve domain parameters. Contains the irreducible that defines
|
||||
the field (either the prime or the binary polynomial) as well as
|
||||
pointers to the functions that should be used for field arithmetic.
|
||||
|
||||
ARITHMETIC FUNCTIONS
|
||||
====================
|
||||
|
||||
Higher-level algorithms (like ECDH and ECDSA) should call ECPoint_mul
|
||||
or ECPoints_mul (from ecl.h) to do point arithmetic. These functions
|
||||
will choose which underlying algorithms to use, based on the ECGroup
|
||||
structure.
|
||||
|
||||
Point Multiplication
|
||||
--------------------
|
||||
|
||||
ecl_mult.c provides the ECPoints_mul and ECPoint_mul wrappers.
|
||||
It also provides two implementations for the pts_mul operation -
|
||||
ec_pts_mul_basic (which computes kP, lQ, and then adds kP + lQ) and
|
||||
ec_pts_mul_simul_w2 (which does a simultaneous point multiplication
|
||||
using a table with window size 2*2).
|
||||
|
||||
ec_naf.c provides an implementation of an algorithm to calculate a
|
||||
non-adjacent form of a scalar, minimizing the number of point
|
||||
additions that need to be done in a point multiplication.
|
||||
|
||||
Point Arithmetic over Prime Fields
|
||||
----------------------------------
|
||||
|
||||
ecp_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ecp_jac.c provides point arithmetic using Jacobian projective
|
||||
coordinates and mixed Jacobian-affine coordinates. (Jacobian projective
|
||||
coordinates represent a point (x, y) as (X, Y, Z), where x=X/Z^2,
|
||||
y=Y/Z^3).
|
||||
|
||||
ecp_jm.c provides point arithmetic using Modified Jacobian
|
||||
coordinates and mixed Modified_Jacobian-affine coordinates.
|
||||
(Modified Jacobian coordinates represent a point (x, y)
|
||||
as (X, Y, Z, a*Z^4), where x=X/Z^2, y=Y/Z^3, and a is
|
||||
the linear coefficient in the curve defining equation).
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized field arithmetic.
|
||||
|
||||
Point Arithmetic over Binary Polynomial Fields
|
||||
----------------------------------------------
|
||||
|
||||
ec2_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ec2_proj.c provides point arithmetic using projective coordinates.
|
||||
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
|
||||
x=X/Z, y=Y/Z^2).
|
||||
|
||||
ec2_mont.c provides point multiplication using Montgomery projective
|
||||
coordinates.
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
|
||||
|
||||
Field Arithmetic
|
||||
----------------
|
||||
|
||||
ecl_gf.c provides constructors for field objects (GFMethod) with the
|
||||
functions GFMethod_cons*. It also provides wrappers around the basic
|
||||
field operations.
|
||||
|
||||
Prime Field Arithmetic
|
||||
----------------------
|
||||
|
||||
The mpi library provides the basic prime field arithmetic.
|
||||
|
||||
ecp_mont.c provides wrappers around the Montgomery multiplication
|
||||
functions from the mpi library and adds encoding and decoding functions.
|
||||
It also provides the function to construct a GFMethod object using
|
||||
Montgomery multiplication.
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized modular reduction for the
|
||||
fields defined by nistp192 and nistp224 primes.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Binary Polynomial Field Arithmetic
|
||||
----------------------------------
|
||||
|
||||
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
|
||||
including addition, multiplication, squaring, mod, and division, as well
|
||||
as conversion ob polynomial representations between bitstring and int[].
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
|
||||
and sqr operations.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Field Encoding
|
||||
--------------
|
||||
|
||||
By default, field elements are encoded in their basic form. It is
|
||||
possible to use an alternative encoding, however. For example, it is
|
||||
possible to Montgomery representation of prime field elements and
|
||||
take advantage of the fast modular multiplication that Montgomery
|
||||
representation provides. The process of converting from basic form to
|
||||
Montgomery representation is called field encoding, and the opposite
|
||||
process would be field decoding. All internal point operations assume
|
||||
that the operands are field encoded as appropriate. By rewiring the
|
||||
underlying field arithmetic to perform operations on these encoded
|
||||
values, the same overlying point arithmetic operations can be used
|
||||
regardless of field representation.
|
||||
|
||||
ALGORITHM WIRING
|
||||
================
|
||||
|
||||
The EC library allows point and field arithmetic algorithms to be
|
||||
substituted ("wired-in") on a fine-grained basis. This allows for
|
||||
generic algorithms and algorithms that are optimized for a particular
|
||||
curve, field, or architecture, to coexist and to be automatically
|
||||
selected at runtime.
|
||||
|
||||
Wiring Mechanism
|
||||
----------------
|
||||
|
||||
The ECGroup and GFMethod structure contain pointers to the point and
|
||||
field arithmetic functions, respectively, that are to be used in
|
||||
operations.
|
||||
|
||||
The selection of algorithms to use is handled in the function
|
||||
ecgroup_fromNameAndHex in ecl.c.
|
||||
|
||||
Default Wiring
|
||||
--------------
|
||||
|
||||
Curves over prime fields by default use montgomery field arithmetic,
|
||||
point multiplication using 5-bit window non-adjacent-form with
|
||||
Modified Jacobian coordinates, and 2*2-bit simultaneous point
|
||||
multiplication using Jacobian coordinates.
|
||||
(Wiring in function ECGroup_consGFp_mont in ecl.c.)
|
||||
|
||||
Curves over prime fields that have optimized modular reduction (i.e.,
|
||||
secp160r1, nistp192, and nistp224) do not use Montgomery field
|
||||
arithmetic. Instead, they use basic field arithmetic with their
|
||||
optimized reduction (as in ecp_192.c and ecp_224.c). They
|
||||
use the same point multiplication and simultaneous point multiplication
|
||||
algorithms as other curves over prime fields.
|
||||
|
||||
Curves over binary polynomial fields by default use generic field
|
||||
arithmetic with montgomery point multiplication and basic kP + lQ
|
||||
computation (multiply, multiply, and add). (Wiring in function
|
||||
ECGroup_cons_GF2m in ecl.c.)
|
||||
|
||||
Curves over binary polynomial fields that have optimized field
|
||||
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
|
||||
field arithmetic. They use the same point multiplication and
|
||||
simultaneous point multiplication algorithms as other curves over binary
|
||||
fields.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
We provide an example for plugging in an optimized implementation for
|
||||
the Koblitz curve nistk163.
|
||||
|
||||
Suppose the file ec2_k163.c contains the optimized implementation. In
|
||||
particular it contains a point multiplication function:
|
||||
|
||||
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
Since only a pt_mul function is provided, the generic pt_add function
|
||||
will be used.
|
||||
|
||||
There are two options for handling the optimized field arithmetic used
|
||||
by the ..._pt_mul function. Say the optimized field arithmetic includes
|
||||
the following functions:
|
||||
|
||||
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
|
||||
First, the optimized field arithmetic could simply be called directly
|
||||
by the ..._pt_mul function. This would be accomplished by changing
|
||||
the ecgroup_fromNameAndHex function in ecl.c to include the following
|
||||
statements:
|
||||
|
||||
if (name == ECCurve_NIST_K163) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
|
||||
&geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK( ec_group_set_nistk163(group) );
|
||||
}
|
||||
|
||||
and including in ec2_k163.c the following function:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
As a result, ec_GF2m_pt_add and similar functions would use the
|
||||
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
|
||||
ec_GF2m_sqr, and ec_GF2m_div.
|
||||
|
||||
Alternatively, the optimized field arithmetic could be wired into the
|
||||
group's GFMethod. This would be accomplished by putting the following
|
||||
function in ec2_k163.c:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->meth->field_add = &ec_GF2m_nistk163_add;
|
||||
group->meth->field_mul = &ec_GF2m_nistk163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
|
||||
group->meth->field_div = &ec_GF2m_nistk163_div;
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
For an example of functions that use special field encodings, take a
|
||||
look at ecp_mont.c.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
|
||||
The ecl/tests directory contains a collection of standalone tests that
|
||||
verify the correctness of the elliptic curve library.
|
||||
|
||||
Both ecp_test and ec2_test take the following arguments:
|
||||
|
||||
--print Print out results of each point arithmetic test.
|
||||
--time Benchmark point operations and print results.
|
||||
|
||||
The set of curves over which ecp_test and ec2_test run is coded into the
|
||||
program, but can be changed by editing the source files.
|
||||
|
||||
BUILDING
|
||||
========
|
||||
|
||||
The ecl can be built as a standalone library, separate from NSS,
|
||||
dependent only on the mpi library. To build the library:
|
||||
|
||||
> cd ../mpi
|
||||
> make libs
|
||||
> cd ../ecl
|
||||
> make libs
|
||||
> make tests # to build test files
|
||||
> make test # to run automated tests
|
||||
@@ -1,317 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the elliptic curve math library.
|
||||
|
||||
The Initial Developer of the Original Code is Sun Microsystems, Inc.
|
||||
Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
|
||||
Sun Microsystems, Inc. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Stephen Fung <fungstep@hotmail.com> and
|
||||
Nils Gura <nils.gura@sun.com>, Sun Microsystems Laboratories
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
The ECL exposes routines for constructing and converting curve
|
||||
parameters for internal use.
|
||||
|
||||
The floating point code of the ECL provides algorithms for performing
|
||||
elliptic-curve point multiplications in floating point.
|
||||
|
||||
The point multiplication algorithms perform calculations almost
|
||||
exclusively in floating point for efficiency, but have the same
|
||||
(integer) interface as the ECL for compatibility and to be easily
|
||||
wired-in to the ECL. Please see README file (not this README.FP file)
|
||||
for information on wiring-in.
|
||||
|
||||
This has been implemented for 3 curves as specified in [1]:
|
||||
secp160r1
|
||||
secp192r1
|
||||
secp224r1
|
||||
|
||||
RATIONALE
|
||||
=========
|
||||
Calculations are done in the floating-point unit (FPU) since it
|
||||
gives better performance on the UltraSPARC III chips. This is
|
||||
because the FPU allows for faster multiplication than the integer unit.
|
||||
The integer unit has a longer multiplication instruction latency, and
|
||||
does not allow full pipelining, as described in [2].
|
||||
Since performance is an important selling feature of Elliptic Curve
|
||||
Cryptography (ECC), this implementation was created.
|
||||
|
||||
DATA REPRESENTATION
|
||||
===================
|
||||
Data is primarily represented in an array of double-precision floating
|
||||
point numbers. Generally, each array element has 24 bits of precision
|
||||
(i.e. be x * 2^y, where x is an integer of at most 24 bits, y some positive
|
||||
integer), although the actual implementation details are more complicated.
|
||||
|
||||
e.g. a way to store an 80 bit number might be:
|
||||
double p[4] = { 632613 * 2^0, 329841 * 2^24, 9961 * 2^48, 51 * 2^64 };
|
||||
See section ARITHMETIC OPERATIONS for more details.
|
||||
|
||||
This implementation assumes that the floating-point unit rounding mode
|
||||
is round-to-even as specified in IEEE 754
|
||||
(as opposed to chopping, rounding up, or rounding down).
|
||||
When subtracting integers represented as arrays of floating point
|
||||
numbers, some coefficients (array elements) may become negative.
|
||||
This effectively gives an extra bit of precision that is important
|
||||
for correctness in some cases.
|
||||
|
||||
The described number presentation limits the size of integers to 1023 bits.
|
||||
This is due to an upper bound of 1024 for the exponent of a double precision
|
||||
floating point number as specified in IEEE-754.
|
||||
However, this is acceptable for ECC key sizes of the foreseeable future.
|
||||
|
||||
DATA STRUCTURES
|
||||
===============
|
||||
For more information on coordinate representations, see [3].
|
||||
|
||||
ecfp_aff_pt
|
||||
-----------
|
||||
Affine EC Point Representation. This is the basic
|
||||
representation (x, y) of an elliptic curve point.
|
||||
|
||||
ecfp_jac_pt
|
||||
-----------
|
||||
Jacobian EC Point. This stores a point as (X, Y, Z), where
|
||||
the affine point corresponds to (X/Z^2, Y/Z^3). This allows
|
||||
for fewer inversions in calculations.
|
||||
|
||||
ecfp_chud_pt
|
||||
------------
|
||||
Chudnovsky Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, Z^2, Z^3), the same as a Jacobian representation
|
||||
but also storing Z^2 and Z^3 for faster point additions.
|
||||
|
||||
ecfp_jm_pt
|
||||
----------
|
||||
Modified Jacobian Point. This representation stores a point
|
||||
as (X, Y, Z, a*Z^4), the same as Jacobian representation but
|
||||
also storing a*Z^4 for faster point doublings. Here "a" represents
|
||||
the linear coefficient of x defining the curve.
|
||||
|
||||
EC_group_fp
|
||||
-----------
|
||||
Stores information on the elliptic curve group for floating
|
||||
point calculations. Contains curve specific information, as
|
||||
well as function pointers to routines, allowing different
|
||||
optimizations to be easily wired in.
|
||||
This should be made accessible from an ECGroup for the floating
|
||||
point implementations of point multiplication.
|
||||
|
||||
POINT MULTIPLICATION ALGORITHMS
|
||||
===============================
|
||||
Elliptic Curve Point multiplication can be done at a higher level orthogonal
|
||||
to the implementation of point additions and point doublings. There
|
||||
are a variety of algorithms that can be used.
|
||||
|
||||
The following algorithms have been implemented:
|
||||
|
||||
4-bit Window (Jacobian Coordinates)
|
||||
Double & Add (Jacobian & Affine Coordinates)
|
||||
5-bit Non-Adjacent Form (Modified Jacobian & Chudnovsky Jacobian)
|
||||
|
||||
Currently, the fastest algorithm for multiplying a generic point
|
||||
is the 5-bit Non-Adjacent Form.
|
||||
|
||||
See comments in ecp_fp.c for more details and references.
|
||||
|
||||
SOURCE / HEADER FILES
|
||||
=====================
|
||||
|
||||
ecp_fp.c
|
||||
--------
|
||||
Main source file for floating point calculations. Contains routines
|
||||
to convert from floating-point to integer (mp_int format), point
|
||||
multiplication algorithms, and several other routines.
|
||||
|
||||
ecp_fp.h
|
||||
--------
|
||||
Main header file. Contains most constants used and function prototypes.
|
||||
|
||||
ecp_fp[160, 192, 224].c
|
||||
-----------------------
|
||||
Source files for specific curves. Contains curve specific code such
|
||||
as specialized reduction based on the field defining prime. Contains
|
||||
code wiring-in different algorithms and optimizations.
|
||||
|
||||
ecp_fpinc.c
|
||||
-----------
|
||||
Source file that is included by ecp_fp[160, 192, 224].c. This generates
|
||||
functions with different preprocessor-defined names and loop iterations,
|
||||
allowing for static linking and strong compiler optimizations without
|
||||
code duplication.
|
||||
|
||||
TESTING
|
||||
=======
|
||||
The test suite can be found in ecl/tests/ecp_fpt. This tests and gets
|
||||
timings of the different algorithms for the curves implemented.
|
||||
|
||||
ARITHMETIC OPERATIONS
|
||||
---------------------
|
||||
The primary operations in ECC over the prime fields are modular arithmetic:
|
||||
i.e. n * m (mod p) and n + m (mod p). In this implementation, multiplication,
|
||||
addition, and reduction are implemented as separate functions. This
|
||||
enables computation of formulae with fewer reductions, e.g.
|
||||
(a * b) + (c * d) (mod p) rather than:
|
||||
((a * b) (mod p)) + ((c * d) (mod p)) (mod p)
|
||||
This takes advantage of the fact that the double precision mantissa in
|
||||
floating point can hold numbers up to 2^53, i.e. it has some leeway to
|
||||
store larger intermediate numbers. See further detail in the section on
|
||||
FLOATING POINT PRECISION.
|
||||
|
||||
Multiplication
|
||||
--------------
|
||||
Multiplication is implemented in a standard polynomial multiplication
|
||||
fashion. The terms in opposite factors are pairwise multiplied and
|
||||
added together appropriately. Note that the result requires twice
|
||||
as many doubles for storage, as the bit size of the product is twice
|
||||
that of the multiplicands.
|
||||
e.g. suppose we have double n[3], m[3], r[6], and want to calculate r = n * m
|
||||
r[0] = n[0] * m[0]
|
||||
r[1] = n[0] * m[1] + n[1] * m[0]
|
||||
r[2] = n[0] * m[2] + n[1] * m[1] + n[2] * m[0]
|
||||
r[3] = n[1] * m[2] + n[2] * m[1]
|
||||
r[4] = n[2] * m[2]
|
||||
r[5] = 0 (This is used later to hold spillover from r[4], see tidying in
|
||||
the reduction section.)
|
||||
|
||||
Addition
|
||||
--------
|
||||
Addition is done term by term. The only caveat is to be careful with
|
||||
the number of terms that need to be added. When adding results of
|
||||
multiplication (before reduction), twice as many terms need to be added
|
||||
together. This is done in the addLong function.
|
||||
e.g. for double n[4], m[4], r[4]: r = n + m
|
||||
r[0] = n[0] + m[0]
|
||||
r[1] = n[1] + m[1]
|
||||
r[2] = n[2] + m[2]
|
||||
r[3] = n[3] + m[3]
|
||||
|
||||
Modular Reduction
|
||||
-----------------
|
||||
For the curves implemented, reduction is possible by fast reduction
|
||||
for Generalized Mersenne Primes, as described in [4]. For the
|
||||
floating point implementation, a significant step of the reduction
|
||||
process is tidying: that is, the propagation of carry bits from
|
||||
low-order to high-order coefficients to reduce the precision of each
|
||||
coefficient to 24 bits.
|
||||
This is done by adding and then subtracting
|
||||
ecfp_alpha, a large floating point number that induces precision roundoff.
|
||||
See [5] for more details on tidying using floating point arithmetic.
|
||||
e.g. suppose we have r = 961838 * 2^24 + 519308
|
||||
then if we set alpha = 3 * 2^51 * 2^24,
|
||||
FP(FP(r + alpha) - alpha) = 961838 * 2^24, because the precision for
|
||||
the intermediate results is limited. Our values of alpha are chosen
|
||||
to truncate to a desired number of bits.
|
||||
|
||||
The reduction is then performed as in [4], adding multiples of prime p.
|
||||
e.g. suppose we are working over a polynomial of 10^2. Take the number
|
||||
2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95, stored in 5 elements
|
||||
for coefficients of 10^0, 10^2, ..., 10^8.
|
||||
We wish to reduce modulo p = 10^6 - 2 * 10^4 + 1
|
||||
We can subtract off from the higher terms
|
||||
(2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95) - (2 * 10^2) * (10^6 - 2 * 10^4 + 1)
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95
|
||||
= 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95 - (15) * (10^6 - 2 * 10^4 + 1)
|
||||
= 83 * 10^4 + 21 * 10^2 + 80
|
||||
|
||||
Integrated Example
|
||||
------------------
|
||||
This example shows how multiplication, addition, tidying, and reduction
|
||||
work together in our modular arithmetic. This is simplified from the
|
||||
actual implementation, but should convey the main concepts.
|
||||
Working over polynomials of 10^2 and with p as in the prior example,
|
||||
Let a = 16 * 10^4 + 53 * 10^2 + 33
|
||||
let b = 81 * 10^4 + 31 * 10^2 + 49
|
||||
let c = 22 * 10^4 + 0 * 10^2 + 95
|
||||
And suppose we want to compute a * b + c mod p.
|
||||
We first do a multiplication: then a * b =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5100 * 10^4 + 3620 * 10^2 + 1617
|
||||
Then we add in c before doing reduction, allowing us to get a * b + c =
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
We then perform a tidying on the upper half of the terms:
|
||||
0 * 10^10 + 1296 * 10^8 + 4789 * 10^6
|
||||
0 * 10^10 + (1296 + 47) * 10^8 + 89 * 10^6
|
||||
0 * 10^10 + 1343 * 10^8 + 89 * 10^6
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6
|
||||
which then gives us
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
we then reduce modulo p similar to the reduction example above:
|
||||
13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (13 * 10^4 * p)
|
||||
69 * 10^8 + 89 * 10^6 + 5109 * 10^4 + 3620 * 10^2 + 1712
|
||||
- (69 * 10^2 * p)
|
||||
227 * 10^6 + 5109 * 10^4 + 3551 * 10^2 + 1712
|
||||
- (227 * p)
|
||||
5563 * 10^4 + 3551 * 10^2 + 1485
|
||||
finally, we do tidying to get the precision of each term down to 2 digits
|
||||
5563 * 10^4 + 3565 * 10^2 + 85
|
||||
5598 * 10^4 + 65 * 10^2 + 85
|
||||
55 * 10^6 + 98 * 10^4 + 65 * 10^2 + 85
|
||||
and perform another reduction step
|
||||
- (55 * p)
|
||||
208 * 10^4 + 65 * 10^2 + 30
|
||||
There may be a small number of further reductions that could be done at
|
||||
this point, but this is typically done only at the end when converting
|
||||
from floating point to an integer unit representation.
|
||||
|
||||
FLOATING POINT PRECISION
|
||||
========================
|
||||
This section discusses the precision of floating point numbers, which
|
||||
one writing new formulae or a larger bit size should be aware of. The
|
||||
danger is that an intermediate result may be required to store a
|
||||
mantissa larger than 53 bits, which would cause error by rounding off.
|
||||
|
||||
Note that the tidying with IEEE rounding mode set to round-to-even
|
||||
allows negative numbers, which actually reduces the size of the double
|
||||
mantissa to 23 bits - since it rounds the mantissa to the nearest number
|
||||
modulo 2^24, i.e. roughly between -2^23 and 2^23.
|
||||
A multiplication increases the bit size to 2^46 * n, where n is the number
|
||||
of doubles to store a number. For the 224 bit curve, n = 10. This gives
|
||||
doubles of size 5 * 2^47. Adding two of these doubles gives a result
|
||||
of size 5 * 2^48, which is less than 2^53, so this is safe.
|
||||
Similar analysis can be done for other formulae to ensure numbers remain
|
||||
below 2^53.
|
||||
|
||||
Extended-Precision Floating Point
|
||||
---------------------------------
|
||||
Some platforms, notably x86 Linux, may use an extended-precision floating
|
||||
point representation that has a 64-bit mantissa. [6] Although this
|
||||
implementation is optimized for the IEEE standard 53-bit mantissa,
|
||||
it should work with the 64-bit mantissa. A check is done at run-time
|
||||
in the function ec_set_fp_precision that detects if the precision is
|
||||
greater than 53 bits, and runs code for the 64-bit mantissa accordingly.
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
[1] Certicom Corp., "SEC 2: Recommended Elliptic Curve Domain Parameters", Sept. 20, 2000. www.secg.org
|
||||
[2] Sun Microsystems Inc. UltraSPARC III Cu User's Manual, Version 1.0, May 2002, Table 4.4
|
||||
[3] H. Cohen, A. Miyaji, and T. Ono, "Efficient Elliptic Curve Exponentiation Using Mixed Coordinates".
|
||||
[4] Henk C.A. van Tilborg, Generalized Mersenne Prime. http://www.win.tue.nl/~henkvt/GenMersenne.pdf
|
||||
[5] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2.
|
||||
[6] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2 Notes.
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ec2_h_
|
||||
#define __ec2_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses affine coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the irreducible that
|
||||
* determines the field GF2m. Uses Montgomery projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). */
|
||||
mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Uses projective coordinates. */
|
||||
mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ec2_h_ */
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 6;
|
||||
|
||||
/* u[5] only has 6 significant bits */
|
||||
z = u[5];
|
||||
u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[3];
|
||||
u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35);
|
||||
u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29);
|
||||
z = u[2] >> 35; /* z only has 29 significant bits */
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[5] = u[4] = u[3] = 0;
|
||||
u[2] ^= z << 35;
|
||||
#else
|
||||
if (MP_USED(r) < 11) {
|
||||
MP_CHECKOK(s_mp_pad(r, 11));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 11;
|
||||
|
||||
/* u[11] only has 6 significant bits */
|
||||
z = u[10];
|
||||
u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[4] ^= (z << 29);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 28) ^ (z >> 29);
|
||||
u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[3] ^= (z << 29);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 28) ^ (z >> 29);
|
||||
u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[2] ^= (z << 29);
|
||||
z = u[7];
|
||||
u[3] ^= (z >> 28) ^ (z >> 29);
|
||||
u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[1] ^= (z << 29);
|
||||
z = u[6];
|
||||
u[2] ^= (z >> 28) ^ (z >> 29);
|
||||
u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3);
|
||||
u[0] ^= (z << 29);
|
||||
z = u[5] >> 3; /* z only has 29 significant bits */
|
||||
u[1] ^= (z >> 25) ^ (z >> 26);
|
||||
u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z;
|
||||
/* clear bits above 163 */
|
||||
u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0;
|
||||
u[5] ^= z << 3;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction
|
||||
* polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 3) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 6) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
if (MP_USED(a) < 6) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 12) {
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
}
|
||||
MP_USED(r) = 12;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
#endif
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 163-bit curve. Assumes
|
||||
* reduction polynomial with terms {163, 7, 6, 3, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0;
|
||||
mp_digit rm[6];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_163_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
#endif
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
#endif
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
MP_USED(r) = 6;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 12));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3);
|
||||
s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0);
|
||||
s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1,
|
||||
b3 ^ b0);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6);
|
||||
MP_DIGIT(r, 8) ^= rm[5];
|
||||
MP_DIGIT(r, 7) ^= rm[4];
|
||||
MP_DIGIT(r, 6) ^= rm[3];
|
||||
MP_DIGIT(r, 5) ^= rm[2];
|
||||
MP_DIGIT(r, 4) ^= rm[1];
|
||||
MP_DIGIT(r, 3) ^= rm[0];
|
||||
MP_USED(r) = 12;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_163_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 163-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m163(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_163_mod;
|
||||
group->meth->field_mul = &ec_GF2m_163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_163_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 7;
|
||||
|
||||
/* u[6] only has 2 significant bits */
|
||||
z = u[6];
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 63);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 50);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 63);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 50);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 63);
|
||||
z = u[3] >> 1; /* z only has 63 significant bits */
|
||||
u[1] ^= (z >> 49);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 1;
|
||||
#else
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 13;
|
||||
|
||||
/* u[12] only has 2 significant bits */
|
||||
z = u[12];
|
||||
u[6] ^= (z << 14) ^ (z >> 1);
|
||||
u[5] ^= (z << 31);
|
||||
z = u[11];
|
||||
u[6] ^= (z >> 18);
|
||||
u[5] ^= (z << 14) ^ (z >> 1);
|
||||
u[4] ^= (z << 31);
|
||||
z = u[10];
|
||||
u[5] ^= (z >> 18);
|
||||
u[4] ^= (z << 14) ^ (z >> 1);
|
||||
u[3] ^= (z << 31);
|
||||
z = u[9];
|
||||
u[4] ^= (z >> 18);
|
||||
u[3] ^= (z << 14) ^ (z >> 1);
|
||||
u[2] ^= (z << 31);
|
||||
z = u[8];
|
||||
u[3] ^= (z >> 18);
|
||||
u[2] ^= (z << 14) ^ (z >> 1);
|
||||
u[1] ^= (z << 31);
|
||||
z = u[7];
|
||||
u[2] ^= (z >> 18);
|
||||
u[1] ^= (z << 14) ^ (z >> 1);
|
||||
u[0] ^= (z << 31);
|
||||
z = u[6] >> 1; /* z only has 31 significant bits */
|
||||
u[1] ^= (z >> 17);
|
||||
u[0] ^= (z << 15) ^ z;
|
||||
/* clear bits above 193 */
|
||||
u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0;
|
||||
u[6] ^= z << 1;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction
|
||||
* polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 7) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
MP_USED(r) = 7;
|
||||
#else
|
||||
if (MP_USED(a) < 7) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 13) {
|
||||
MP_CHECKOK(s_mp_pad(r, 13));
|
||||
}
|
||||
MP_USED(r) = 13;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
#endif
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 193-bit curve. Assumes
|
||||
* reduction polynomial with terms {193, 15, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_193_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 14));
|
||||
s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1,
|
||||
b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7);
|
||||
rm[6] ^= MP_DIGIT(r, 6);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 14;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_193_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 193-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m193(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_193_mod;
|
||||
group->meth->field_mul = &ec_GF2m_193_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_193_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "mp_gf2m-priv.h"
|
||||
#include "mpi.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, z;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 8;
|
||||
|
||||
/* u[7] only has 18 significant bits */
|
||||
z = u[7];
|
||||
u[4] ^= (z << 33) ^ (z >> 41);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[6];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 33) ^ (z >> 41);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[5];
|
||||
u[3] ^= (z >> 31);
|
||||
u[2] ^= (z << 33) ^ (z >> 41);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[4];
|
||||
u[2] ^= (z >> 31);
|
||||
u[1] ^= (z << 33) ^ (z >> 41);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[3] >> 41; /* z only has 23 significant bits */
|
||||
u[1] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[7] = u[6] = u[5] = u[4] = 0;
|
||||
u[3] ^= z << 41;
|
||||
#else
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
u = MP_DIGITS(r);
|
||||
MP_USED(r) = 15;
|
||||
|
||||
/* u[14] only has 18 significant bits */
|
||||
z = u[14];
|
||||
u[9] ^= (z << 1);
|
||||
u[7] ^= (z >> 9);
|
||||
u[6] ^= (z << 23);
|
||||
z = u[13];
|
||||
u[9] ^= (z >> 31);
|
||||
u[8] ^= (z << 1);
|
||||
u[6] ^= (z >> 9);
|
||||
u[5] ^= (z << 23);
|
||||
z = u[12];
|
||||
u[8] ^= (z >> 31);
|
||||
u[7] ^= (z << 1);
|
||||
u[5] ^= (z >> 9);
|
||||
u[4] ^= (z << 23);
|
||||
z = u[11];
|
||||
u[7] ^= (z >> 31);
|
||||
u[6] ^= (z << 1);
|
||||
u[4] ^= (z >> 9);
|
||||
u[3] ^= (z << 23);
|
||||
z = u[10];
|
||||
u[6] ^= (z >> 31);
|
||||
u[5] ^= (z << 1);
|
||||
u[3] ^= (z >> 9);
|
||||
u[2] ^= (z << 23);
|
||||
z = u[9];
|
||||
u[5] ^= (z >> 31);
|
||||
u[4] ^= (z << 1);
|
||||
u[2] ^= (z >> 9);
|
||||
u[1] ^= (z << 23);
|
||||
z = u[8];
|
||||
u[4] ^= (z >> 31);
|
||||
u[3] ^= (z << 1);
|
||||
u[1] ^= (z >> 9);
|
||||
u[0] ^= (z << 23);
|
||||
z = u[7] >> 9; /* z only has 23 significant bits */
|
||||
u[3] ^= (z >> 22);
|
||||
u[2] ^= (z << 10);
|
||||
u[0] ^= z;
|
||||
/* clear bits above 233 */
|
||||
u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0;
|
||||
u[7] ^= z << 9;
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction
|
||||
* polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit *u, *v;
|
||||
|
||||
v = MP_DIGITS(a);
|
||||
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
if (MP_USED(a) < 4) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 8) {
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
}
|
||||
MP_USED(r) = 8;
|
||||
#else
|
||||
if (MP_USED(a) < 8) {
|
||||
return mp_bsqrmod(a, meth->irr_arr, r);
|
||||
}
|
||||
if (MP_USED(r) < 15) {
|
||||
MP_CHECKOK(s_mp_pad(r, 15));
|
||||
}
|
||||
MP_USED(r) = 15;
|
||||
#endif
|
||||
u = MP_DIGITS(r);
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
u[14] = gf2m_SQR0(v[7]);
|
||||
u[13] = gf2m_SQR1(v[6]);
|
||||
u[12] = gf2m_SQR0(v[6]);
|
||||
u[11] = gf2m_SQR1(v[5]);
|
||||
u[10] = gf2m_SQR0(v[5]);
|
||||
u[9] = gf2m_SQR1(v[4]);
|
||||
u[8] = gf2m_SQR0(v[4]);
|
||||
#endif
|
||||
u[7] = gf2m_SQR1(v[3]);
|
||||
u[6] = gf2m_SQR0(v[3]);
|
||||
u[5] = gf2m_SQR1(v[2]);
|
||||
u[4] = gf2m_SQR0(v[2]);
|
||||
u[3] = gf2m_SQR1(v[1]);
|
||||
u[2] = gf2m_SQR0(v[1]);
|
||||
u[1] = gf2m_SQR1(v[0]);
|
||||
u[0] = gf2m_SQR0(v[0]);
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Fast multiplication for polynomials over a 233-bit curve. Assumes
|
||||
* reduction polynomial with terms {233, 74, 0}. */
|
||||
mp_err
|
||||
ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 =
|
||||
0;
|
||||
mp_digit rm[8];
|
||||
#endif
|
||||
|
||||
if (a == b) {
|
||||
return ec_GF2m_233_sqr(a, r, meth);
|
||||
} else {
|
||||
switch (MP_USED(a)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
#endif
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a, 2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a, 1);
|
||||
default:
|
||||
a0 = MP_DIGIT(a, 0);
|
||||
}
|
||||
switch (MP_USED(b)) {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
case 8:
|
||||
b7 = MP_DIGIT(b, 7);
|
||||
case 7:
|
||||
b6 = MP_DIGIT(b, 6);
|
||||
case 6:
|
||||
b5 = MP_DIGIT(b, 5);
|
||||
case 5:
|
||||
b4 = MP_DIGIT(b, 4);
|
||||
#endif
|
||||
case 4:
|
||||
b3 = MP_DIGIT(b, 3);
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b, 2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b, 1);
|
||||
default:
|
||||
b0 = MP_DIGIT(b, 0);
|
||||
}
|
||||
#ifdef ECL_SIXTY_FOUR_BIT
|
||||
MP_CHECKOK(s_mp_pad(r, 8));
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
MP_USED(r) = 8;
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
MP_CHECKOK(s_mp_pad(r, 16));
|
||||
s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4);
|
||||
s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0);
|
||||
s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3,
|
||||
b6 ^ b2, b5 ^ b1, b4 ^ b0);
|
||||
rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15);
|
||||
rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14);
|
||||
rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13);
|
||||
rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12);
|
||||
rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11);
|
||||
rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10);
|
||||
rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9);
|
||||
rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8);
|
||||
MP_DIGIT(r, 11) ^= rm[7];
|
||||
MP_DIGIT(r, 10) ^= rm[6];
|
||||
MP_DIGIT(r, 9) ^= rm[5];
|
||||
MP_DIGIT(r, 8) ^= rm[4];
|
||||
MP_DIGIT(r, 7) ^= rm[3];
|
||||
MP_DIGIT(r, 6) ^= rm[2];
|
||||
MP_DIGIT(r, 5) ^= rm[1];
|
||||
MP_DIGIT(r, 4) ^= rm[0];
|
||||
MP_USED(r) = 16;
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
return ec_GF2m_233_mod(r, r, meth);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic for 233-bit curves. */
|
||||
mp_err
|
||||
ec_group_set_gf2m233(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
group->meth->field_mod = &ec_GF2m_233_mod;
|
||||
group->meth->field_mul = &ec_GF2m_233_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_233_sqr;
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2
|
||||
* + lambda + px + qx */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, qx, &tempx, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qx = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = qx + qy / qx */
|
||||
MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&lambda, qx, &lambda, group->meth));
|
||||
/* tempx = a + lambda^2 + lambda */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
}
|
||||
/* ry = (qx + tempx) * lambda + tempx + qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempy, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth));
|
||||
/* rx = tempx */
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = qx+qy */
|
||||
MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth));
|
||||
MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group));
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return group->point_add(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GF2m curve. */
|
||||
mp_err
|
||||
ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 + x*y */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x^2 + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery
|
||||
* projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J.
|
||||
* and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m)
|
||||
* without precomputation". modified to not require precomputation of
|
||||
* c=b^{2^{m-1}}. */
|
||||
static mp_err
|
||||
gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, x, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in
|
||||
* Montgomery projective coordinates. Uses algorithm Madd in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". */
|
||||
static mp_err
|
||||
gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t1, t2;
|
||||
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&t2) = 0;
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&t2));
|
||||
|
||||
MP_CHECKOK(mp_copy(x, &t1));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t1);
|
||||
mp_clear(&t2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation". Returns: 0 on error 1 if return value
|
||||
* should be the point at infinity 2 otherwise */
|
||||
static int
|
||||
gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
|
||||
mp_int *x2, mp_int *z2, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int ret = 0;
|
||||
mp_int t3, t4, t5;
|
||||
|
||||
MP_DIGITS(&t3) = 0;
|
||||
MP_DIGITS(&t4) = 0;
|
||||
MP_DIGITS(&t5) = 0;
|
||||
MP_CHECKOK(mp_init(&t3));
|
||||
MP_CHECKOK(mp_init(&t4));
|
||||
MP_CHECKOK(mp_init(&t5));
|
||||
|
||||
if (mp_cmp_z(z1) == 0) {
|
||||
mp_zero(x2);
|
||||
mp_zero(z2);
|
||||
ret = 1;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_z(z2) == 0) {
|
||||
MP_CHECKOK(mp_copy(x, x2));
|
||||
MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth));
|
||||
ret = 2;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_set_int(&t5, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth));
|
||||
|
||||
MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth));
|
||||
|
||||
ret = 2;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t3);
|
||||
mp_clear(&t4);
|
||||
mp_clear(&t5);
|
||||
if (res == MP_OKAY) {
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast
|
||||
* multiplication on elliptic curves over GF(2^m) without
|
||||
* precomputation". Elliptic curve points P and R can be identical. Uses
|
||||
* Montgomery projective coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int x1, x2, z1, z2;
|
||||
int i, j;
|
||||
mp_digit top_bit, mask;
|
||||
|
||||
MP_DIGITS(&x1) = 0;
|
||||
MP_DIGITS(&x2) = 0;
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&x1));
|
||||
MP_CHECKOK(mp_init(&x2));
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */
|
||||
MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 =
|
||||
* x1^2 =
|
||||
* px^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2
|
||||
* =
|
||||
* px^4
|
||||
* +
|
||||
* b
|
||||
*/
|
||||
|
||||
/* find top-most bit and go one past it */
|
||||
i = MP_USED(n) - 1;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
top_bit = 1;
|
||||
top_bit <<= MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
while (!(MP_DIGITS(n)[i] & mask)) {
|
||||
mask >>= 1;
|
||||
j--;
|
||||
}
|
||||
mask >>= 1;
|
||||
j--;
|
||||
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
for (; j >= 0; j--) {
|
||||
if (MP_DIGITS(n)[i] & mask) {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group));
|
||||
} else {
|
||||
MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group));
|
||||
MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group));
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
j = MP_DIGIT_BIT - 1;
|
||||
mask = top_bit;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group);
|
||||
if (i == 0) {
|
||||
res = MP_BADARG;
|
||||
goto CLEANUP;
|
||||
} else if (i == 1) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&x2, rx));
|
||||
MP_CHECKOK(mp_copy(&z2, ry));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&x1);
|
||||
mp_clear(&x2);
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
@@ -1,369 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ec2.h"
|
||||
#include "mplogic.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* by default, these routines are unused and thus don't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* Converts a point P(px, py) from affine coordinates to projective
|
||||
* coordinates R(rx, ry, rz). Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from projective coordinates to affine
|
||||
* coordinates R(rx, ry). P and R can share x and y coordinates. Assumes
|
||||
* input is already field-encoded using field_enc, and returns output that
|
||||
* is still field-encoded. */
|
||||
mp_err
|
||||
ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz, py / pz^2) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z1, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z2, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses projective
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed projective-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (3) from Hankerson, Hernandez, Menezes.
|
||||
* Software Implementation of Elliptic Curve Cryptography Over Binary
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, E, F, G;
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_aff2proj(qx, qy, rx, ry, rz, group);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
return mp_copy(pz, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&E) = 0;
|
||||
MP_DIGITS(&F) = 0;
|
||||
MP_DIGITS(&G) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&E));
|
||||
MP_CHECKOK(mp_init(&F));
|
||||
MP_CHECKOK(mp_init(&G));
|
||||
|
||||
/* D = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &D, group->meth));
|
||||
|
||||
/* A = qy * pz^2 + py */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &D, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&A, py, &A, group->meth));
|
||||
|
||||
/* B = qx * pz + px */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&B, px, &B, group->meth));
|
||||
|
||||
/* C = pz * B */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &B, &C, group->meth));
|
||||
|
||||
/* D = B^2 * (C + a * pz^2) (using E as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C, &D, &D, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&B, &E, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &D, &D, group->meth));
|
||||
|
||||
/* rz = C^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, rz, group->meth));
|
||||
|
||||
/* E = A * C */
|
||||
MP_CHECKOK(group->meth->field_mul(&A, &C, &E, group->meth));
|
||||
|
||||
/* rx = A^2 + D + E */
|
||||
MP_CHECKOK(group->meth->field_sqr(&A, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &D, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &E, rx, group->meth));
|
||||
|
||||
/* F = rx + qx * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qx, rz, &F, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &F, &F, group->meth));
|
||||
|
||||
/* G = rx + qy * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(qy, rz, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(rx, &G, &G, group->meth));
|
||||
|
||||
/* ry = E * F + rz * G (using G as a temporary variable) */
|
||||
MP_CHECKOK(group->meth->field_mul(rz, &G, &G, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&E, &F, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &G, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&E);
|
||||
mp_clear(&F);
|
||||
mp_clear(&G);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* projective coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* Uses equation (3) from Hankerson, Hernandez, Menezes. Software
|
||||
* Implementation of Elliptic Curve Cryptography Over Binary Fields.
|
||||
*/
|
||||
mp_err
|
||||
ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1;
|
||||
|
||||
if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) {
|
||||
return ec_GF2m_pt_set_inf_proj(rx, ry, rz);
|
||||
}
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
|
||||
/* t0 = px^2 */
|
||||
/* t1 = pz^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &t1, group->meth));
|
||||
|
||||
/* rz = px^2 * pz^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, rz, group->meth));
|
||||
|
||||
/* t0 = px^4 */
|
||||
/* t1 = b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curveb, &t1, &t1, group->meth));
|
||||
|
||||
/* rx = px^4 + b * pz^4 */
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t1, rx, group->meth));
|
||||
|
||||
/* ry = b * pz^4 * rz + rx * (a * rz + py^2 + b * pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(ry, &t1, ry, group->meth));
|
||||
/* t0 = a * rz */
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&group->curvea, rz, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(rx, ry, ry, group->meth));
|
||||
/* t1 = b * pz^4 * rz */
|
||||
MP_CHECKOK(group->meth->field_mul(&t1, rz, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t1, ry, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GF2m. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed projective-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 16 * 2], *t;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
t = precomp_arr;
|
||||
for (i = 0; i < 16; i++) {
|
||||
/* x co-ord */
|
||||
MP_SIGN(&precomp[i][0]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][0]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][0]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][0]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
/* y co-ord */
|
||||
MP_SIGN(&precomp[i][1]) = MP_ZPOS;
|
||||
MP_ALLOC(&precomp[i][1]) = ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
MP_USED(&precomp[i][1]) = 1;
|
||||
*t = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = t;
|
||||
t += ECL_MAX_FIELD_SIZE_DIGITS;
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GF2m_pt_set_inf_proj(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GF2m_pt_add_proj
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GF2m_pt_proj2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int
|
||||
ec_twoTo(int e)
|
||||
{
|
||||
int a = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < e; i++) {
|
||||
a *= 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err
|
||||
ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, int w)
|
||||
{
|
||||
mp_int k;
|
||||
mp_err res = MP_OKAY;
|
||||
int i, twowm1, mask;
|
||||
|
||||
twowm1 = ec_twoTo(w - 1);
|
||||
mask = 2 * twowm1 - 1;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_CHECKOK(mp_init_copy(&k, in));
|
||||
|
||||
i = 0;
|
||||
/* Compute wNAF form */
|
||||
while (mp_cmp_z(&k) > 0) {
|
||||
if (mp_isodd(&k)) {
|
||||
out[i] = MP_DIGIT(&k, 0) & mask;
|
||||
if (out[i] >= twowm1)
|
||||
out[i] -= 2 * twowm1;
|
||||
|
||||
/* Subtract off out[i]. Note mp_sub_d only works with
|
||||
* unsigned digits */
|
||||
if (out[i] >= 0) {
|
||||
mp_sub_d(&k, out[i], &k);
|
||||
} else {
|
||||
mp_add_d(&k, -(out[i]), &k);
|
||||
}
|
||||
} else {
|
||||
out[i] = 0;
|
||||
}
|
||||
mp_div_2(&k, &k);
|
||||
i++;
|
||||
}
|
||||
/* Zero out the remaining elements of the out array. */
|
||||
for (; i < bitsize + 1; i++) {
|
||||
out[i] = 0;
|
||||
}
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
return res;
|
||||
|
||||
}
|
||||
@@ -1,652 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ecl_curve_h_
|
||||
#define __ecl_curve_h_
|
||||
|
||||
#ifndef NSS_ECC_MORE_THAN_SUITE_B
|
||||
#error This source file is for Extended ECC only .
|
||||
#endif
|
||||
|
||||
/* NIST prime curves */
|
||||
static const ECCurveParams ecCurve_NIST_P192 = {
|
||||
"NIST-P192", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
||||
"07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_P224 = {
|
||||
"NIST-P224", ECField_GFp, 224,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
||||
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
||||
"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_P256 = {
|
||||
"NIST-P256", ECField_GFp, 256,
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_P384 = {
|
||||
"NIST-P384", ECField_GFp, 384,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||
1
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_P521 = {
|
||||
"NIST-P521", ECField_GFp, 521,
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||
1
|
||||
};
|
||||
|
||||
/* NIST binary curves */
|
||||
static const ECCurveParams ecCurve_NIST_K163 = {
|
||||
"NIST-K163", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
|
||||
"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
|
||||
"04000000000000000000020108A2E0CC0D99F8A5EF", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_B163 = {
|
||||
"NIST-B163", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"000000000000000000000000000000000000000001",
|
||||
"020A601907B8C953CA1481EB10512F78744A3205FD",
|
||||
"03F0EBA16286A2D57EA0991168D4994637E8343E36",
|
||||
"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
|
||||
"040000000000000000000292FE77E70C12A4234C33", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_K233 = {
|
||||
"NIST-K233", ECField_GF2m, 233,
|
||||
"020000000000000000000000000000000000000004000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
|
||||
"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
|
||||
"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_B233 = {
|
||||
"NIST-B233", ECField_GF2m, 233,
|
||||
"020000000000000000000000000000000000000004000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
|
||||
"00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
|
||||
"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
|
||||
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_K283 = {
|
||||
"NIST-K283", ECField_GF2m, 283,
|
||||
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
|
||||
"01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
|
||||
4
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_B283 = {
|
||||
"NIST-B283", ECField_GF2m, 283,
|
||||
"0800000000000000000000000000000000000000000000000000000000000000000010A1",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
|
||||
"05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
|
||||
"03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
|
||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
|
||||
2
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_K409 = {
|
||||
"NIST-K409", ECField_GF2m, 409,
|
||||
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
|
||||
"01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
|
||||
"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
|
||||
4
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_B409 = {
|
||||
"NIST-B409", ECField_GF2m, 409,
|
||||
"02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
|
||||
"015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
|
||||
"0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
|
||||
"010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
|
||||
2
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_K571 = {
|
||||
"NIST-K571", ECField_GF2m, 571,
|
||||
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
|
||||
"0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
|
||||
"020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
|
||||
4
|
||||
};
|
||||
static const ECCurveParams ecCurve_NIST_B571 = {
|
||||
"NIST-B571", ECField_GF2m, 571,
|
||||
"080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
||||
"02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
|
||||
"0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
|
||||
"037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
|
||||
"03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
|
||||
2
|
||||
};
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_192V2 = {
|
||||
"X9.62 P-192V2", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
|
||||
"EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
|
||||
"6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_192V3 = {
|
||||
"X9.62 P-192V3", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
|
||||
"7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
|
||||
"38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V1 = {
|
||||
"X9.62 P-239V1", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
|
||||
"0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
|
||||
"7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V2 = {
|
||||
"X9.62 P-239V2", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
|
||||
"38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
|
||||
"5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_PRIME_239V3 = {
|
||||
"X9.62 P-239V3", ECField_GFp, 239,
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||
"255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
|
||||
"6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
|
||||
"1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
|
||||
"7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", 1
|
||||
};
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V1 = {
|
||||
"X9.62 C2-PNB163V1", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"072546B5435234A422E0789675F432C89435DE5242",
|
||||
"00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9",
|
||||
"07AF69989546103D79329FCC3D74880F33BBE803CB",
|
||||
"01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F",
|
||||
"0400000000000000000001E60FC8821CC74DAEAFC1", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V2 = {
|
||||
"X9.62 C2-PNB163V2", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"0108B39E77C4B108BED981ED0E890E117C511CF072",
|
||||
"0667ACEB38AF4E488C407433FFAE4F1C811638DF20",
|
||||
"0024266E4EB5106D0A964D92C4860E2671DB9B6CC5",
|
||||
"079F684DDF6684C5CD258B3890021B2386DFD19FC5",
|
||||
"03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V3 = {
|
||||
"X9.62 C2-PNB163V3", ECField_GF2m, 163,
|
||||
"080000000000000000000000000000000000000107",
|
||||
"07A526C63D3E25A256A007699F5447E32AE456B50E",
|
||||
"03F7061798EB99E238FD6F1BF95B48FEEB4854252B",
|
||||
"02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB",
|
||||
"05B935590C155E17EA48EB3FF3718B893DF59A05D0",
|
||||
"03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB176V1 = {
|
||||
"X9.62 C2-PNB176V1", ECField_GF2m, 176,
|
||||
"0100000000000000000000000000000000080000000007",
|
||||
"E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B",
|
||||
"5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2",
|
||||
"8D16C2866798B600F9F08BB4A8E860F3298CE04A5798",
|
||||
"6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C",
|
||||
"00010092537397ECA4F6145799D62B0A19CE06FE26AD", 0xFF6E
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V1 = {
|
||||
"X9.62 C2-TNB191V1", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"2866537B676752636A68F56554E12640276B649EF7526267",
|
||||
"2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC",
|
||||
"36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D",
|
||||
"765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB",
|
||||
"40000000000000000000000004A20E90C39067C893BBB9A5", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V2 = {
|
||||
"X9.62 C2-TNB191V2", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"401028774D7777C7B7666D1366EA432071274F89FF01E718",
|
||||
"0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01",
|
||||
"3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10",
|
||||
"17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A",
|
||||
"20000000000000000000000050508CB89F652824E06B8173", 4
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V3 = {
|
||||
"X9.62 C2-TNB191V3", ECField_GF2m, 191,
|
||||
"800000000000000000000000000000000000000000000201",
|
||||
"6C01074756099122221056911C77D77E77A777E7E7E77FCB",
|
||||
"71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8",
|
||||
"375D4CE24FDE434489DE8746E71786015009E66E38A926DD",
|
||||
"545A39176196575D985999366E6AD34CE0A77CD7127B06BE",
|
||||
"155555555555555555555555610C0B196812BFB6288A3EA3", 6
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB208W1 = {
|
||||
"X9.62 C2-PNB208W1", ECField_GF2m, 208,
|
||||
"010000000000000000000000000000000800000000000000000007",
|
||||
"0000000000000000000000000000000000000000000000000000",
|
||||
"C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E",
|
||||
"89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A",
|
||||
"0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3",
|
||||
"000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 0xFE48
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V1 = {
|
||||
"X9.62 C2-TNB239V1", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"32010857077C5431123A46B808906756F543423E8D27877578125778AC76",
|
||||
"790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16",
|
||||
"57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D",
|
||||
"61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305",
|
||||
"2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 4
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V2 = {
|
||||
"X9.62 C2-TNB239V2", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F",
|
||||
"5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B",
|
||||
"28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205",
|
||||
"5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833",
|
||||
"1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 6
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V3 = {
|
||||
"X9.62 C2-TNB239V3", ECField_GF2m, 239,
|
||||
"800000000000000000000000000000000000000000000000001000000001",
|
||||
"01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F",
|
||||
"6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40",
|
||||
"70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92",
|
||||
"2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461",
|
||||
"0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 0xA
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB272W1 = {
|
||||
"X9.62 C2-PNB272W1", ECField_GF2m, 272,
|
||||
"010000000000000000000000000000000000000000000000000000010000000000000B",
|
||||
"91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20",
|
||||
"7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7",
|
||||
"6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D",
|
||||
"10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23",
|
||||
"000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521",
|
||||
0xFF06
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB304W1 = {
|
||||
"X9.62 C2-PNB304W1", ECField_GF2m, 304,
|
||||
"010000000000000000000000000000000000000000000000000000000000000000000000000807",
|
||||
"FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681",
|
||||
"BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE",
|
||||
"197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614",
|
||||
"E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B",
|
||||
"000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D",
|
||||
0xFE2E
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB359V1 = {
|
||||
"X9.62 C2-TNB359V1", ECField_GF2m, 359,
|
||||
"800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001",
|
||||
"5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557",
|
||||
"2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988",
|
||||
"3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097",
|
||||
"53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD",
|
||||
"01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B",
|
||||
0x4C
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_PNB368W1 = {
|
||||
"X9.62 C2-PNB368W1", ECField_GF2m, 368,
|
||||
"0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007",
|
||||
"E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D",
|
||||
"FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A",
|
||||
"1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F",
|
||||
"7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310",
|
||||
"00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967",
|
||||
0xFF70
|
||||
};
|
||||
static const ECCurveParams ecCurve_X9_62_CHAR2_TNB431R1 = {
|
||||
"X9.62 C2-TNB431R1", ECField_GF2m, 431,
|
||||
"800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001",
|
||||
"1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F",
|
||||
"10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618",
|
||||
"120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7",
|
||||
"20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760",
|
||||
"0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91",
|
||||
0x2760
|
||||
};
|
||||
|
||||
/* SEC2 prime curves */
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_112R1 = {
|
||||
"SECP-112R1", ECField_GFp, 112,
|
||||
"DB7C2ABF62E35E668076BEAD208B",
|
||||
"DB7C2ABF62E35E668076BEAD2088",
|
||||
"659EF8BA043916EEDE8911702B22",
|
||||
"09487239995A5EE76B55F9C2F098",
|
||||
"A89CE5AF8724C0A23E0E0FF77500",
|
||||
"DB7C2ABF62E35E7628DFAC6561C5", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_112R2 = {
|
||||
"SECP-112R2", ECField_GFp, 112,
|
||||
"DB7C2ABF62E35E668076BEAD208B",
|
||||
"6127C24C05F38A0AAAF65C0EF02C",
|
||||
"51DEF1815DB5ED74FCC34C85D709",
|
||||
"4BA30AB5E892B4E1649DD0928643",
|
||||
"adcd46f5882e3747def36e956e97",
|
||||
"36DF0AAFD8B8D7597CA10520D04B", 4
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_128R1 = {
|
||||
"SECP-128R1", ECField_GFp, 128,
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"E87579C11079F43DD824993C2CEE5ED3",
|
||||
"161FF7528B899B2D0C28607CA52C5B86",
|
||||
"CF5AC8395BAFEB13C02DA292DDED7A83",
|
||||
"FFFFFFFE0000000075A30D1B9038A115", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_128R2 = {
|
||||
"SECP-128R2", ECField_GFp, 128,
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"D6031998D1B3BBFEBF59CC9BBFF9AEE1",
|
||||
"5EEEFCA380D02919DC2C6558BB6D8A5D",
|
||||
"7B6AA5D85E572983E6FB32A7CDEBC140",
|
||||
"27B6916A894D3AEE7106FE805FC34B44",
|
||||
"3FFFFFFF7FFFFFFFBE0024720613B5A3", 4
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160K1 = {
|
||||
"SECP-160K1", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||
"0000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000007",
|
||||
"3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
|
||||
"938CF935318FDCED6BC28286531733C3F03C4FEE",
|
||||
"0100000000000000000001B8FA16DFAB9ACA16B6B3", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160R1 = {
|
||||
"SECP-160R1", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
||||
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
||||
"4A96B5688EF573284664698968C38BB913CBFC82",
|
||||
"23A628553168947D59DCC912042351377AC5FB32",
|
||||
"0100000000000000000001F4C8F927AED3CA752257", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_160R2 = {
|
||||
"SECP-160R2", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
|
||||
"B4E134D3FB59EB8BAB57274904664D5AF50388BA",
|
||||
"52DCB034293A117E1F4FF11B30F7199D3144CE6D",
|
||||
"FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
|
||||
"0100000000000000000000351EE786A818F3A1A16B", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_192K1 = {
|
||||
"SECP-192K1", ECField_GFp, 192,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
|
||||
"000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000003",
|
||||
"DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
|
||||
"9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_224K1 = {
|
||||
"SECP-224K1", ECField_GFp, 224,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
|
||||
"00000000000000000000000000000000000000000000000000000000",
|
||||
"00000000000000000000000000000000000000000000000000000005",
|
||||
"A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
|
||||
"7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
|
||||
"010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_PRIME_256K1 = {
|
||||
"SECP-256K1", ECField_GFp, 256,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||
"483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 1
|
||||
};
|
||||
|
||||
/* SEC2 binary curves */
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_113R1 = {
|
||||
"SECT-113R1", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"003088250CA6E7C7FE649CE85820F7",
|
||||
"00E8BEE4D3E2260744188BE0E9C723",
|
||||
"009D73616F35F4AB1407D73562C10F",
|
||||
"00A52830277958EE84D1315ED31886",
|
||||
"0100000000000000D9CCEC8A39E56F", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_113R2 = {
|
||||
"SECT-113R2", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"00689918DBEC7E5A0DD6DFC0AA55C7",
|
||||
"0095E9A9EC9B297BD4BF36E059184F",
|
||||
"01A57A6A7B26CA5EF52FCDB8164797",
|
||||
"00B3ADC94ED1FE674C06E695BABA1D",
|
||||
"010000000000000108789B2496AF93", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_131R1 = {
|
||||
"SECT-131R1", ECField_GF2m, 131,
|
||||
"080000000000000000000000000000010D",
|
||||
"07A11B09A76B562144418FF3FF8C2570B8",
|
||||
"0217C05610884B63B9C6C7291678F9D341",
|
||||
"0081BAF91FDF9833C40F9C181343638399",
|
||||
"078C6E7EA38C001F73C8134B1B4EF9E150",
|
||||
"0400000000000000023123953A9464B54D", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_131R2 = {
|
||||
"SECT-131R2", ECField_GF2m, 131,
|
||||
"080000000000000000000000000000010D",
|
||||
"03E5A88919D7CAFCBF415F07C2176573B2",
|
||||
"04B8266A46C55657AC734CE38F018F2192",
|
||||
"0356DCD8F2F95031AD652D23951BB366A8",
|
||||
"0648F06D867940A5366D9E265DE9EB240F",
|
||||
"0400000000000000016954A233049BA98F", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_163R1 = {
|
||||
"SECT-163R1", ECField_GF2m, 163,
|
||||
"0800000000000000000000000000000000000000C9",
|
||||
"07B6882CAAEFA84F9554FF8428BD88E246D2782AE2",
|
||||
"0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9",
|
||||
"0369979697AB43897789566789567F787A7876A654",
|
||||
"00435EDB42EFAFB2989D51FEFCE3C80988F41FF883",
|
||||
"03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_193R1 = {
|
||||
"SECT-193R1", ECField_GF2m, 193,
|
||||
"02000000000000000000000000000000000000000000008001",
|
||||
"0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01",
|
||||
"00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814",
|
||||
"01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1",
|
||||
"0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05",
|
||||
"01000000000000000000000000C7F34A778F443ACC920EBA49", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_193R2 = {
|
||||
"SECT-193R2", ECField_GF2m, 193,
|
||||
"02000000000000000000000000000000000000000000008001",
|
||||
"0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B",
|
||||
"00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE",
|
||||
"00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F",
|
||||
"01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C",
|
||||
"010000000000000000000000015AAB561B005413CCD4EE99D5", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_SECG_CHAR2_239K1 = {
|
||||
"SECT-239K1", ECField_GF2m, 239,
|
||||
"800000000000000000004000000000000000000000000000000000000001",
|
||||
"000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000000000000000000000000000000000000000000000000000000001",
|
||||
"29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC",
|
||||
"76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA",
|
||||
"2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", 4
|
||||
};
|
||||
|
||||
/* WTLS curves */
|
||||
static const ECCurveParams ecCurve_WTLS_1 = {
|
||||
"WTLS-1", ECField_GF2m, 113,
|
||||
"020000000000000000000000000201",
|
||||
"000000000000000000000000000001",
|
||||
"000000000000000000000000000001",
|
||||
"01667979A40BA497E5D5C270780617",
|
||||
"00F44B4AF1ECC2630E08785CEBCC15",
|
||||
"00FFFFFFFFFFFFFFFDBF91AF6DEA73", 2
|
||||
};
|
||||
static const ECCurveParams ecCurve_WTLS_8 = {
|
||||
"WTLS-8", ECField_GFp, 112,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFDE7",
|
||||
"0000000000000000000000000000",
|
||||
"0000000000000000000000000003",
|
||||
"0000000000000000000000000001",
|
||||
"0000000000000000000000000002",
|
||||
"0100000000000001ECEA551AD837E9", 1
|
||||
};
|
||||
static const ECCurveParams ecCurve_WTLS_9 = {
|
||||
"WTLS-9", ECField_GFp, 160,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F",
|
||||
"0000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000003",
|
||||
"0000000000000000000000000000000000000001",
|
||||
"0000000000000000000000000000000000000002",
|
||||
"0100000000000000000001CDC98AE0E2DE574ABF33", 1
|
||||
};
|
||||
|
||||
/* mapping between ECCurveName enum and pointers to ECCurveParams */
|
||||
static const ECCurveParams *ecCurve_map[] = {
|
||||
NULL, /* ECCurve_noName */
|
||||
&ecCurve_NIST_P192, /* ECCurve_NIST_P192 */
|
||||
&ecCurve_NIST_P224, /* ECCurve_NIST_P224 */
|
||||
&ecCurve_NIST_P256, /* ECCurve_NIST_P256 */
|
||||
&ecCurve_NIST_P384, /* ECCurve_NIST_P384 */
|
||||
&ecCurve_NIST_P521, /* ECCurve_NIST_P521 */
|
||||
&ecCurve_NIST_K163, /* ECCurve_NIST_K163 */
|
||||
&ecCurve_NIST_B163, /* ECCurve_NIST_B163 */
|
||||
&ecCurve_NIST_K233, /* ECCurve_NIST_K233 */
|
||||
&ecCurve_NIST_B233, /* ECCurve_NIST_B233 */
|
||||
&ecCurve_NIST_K283, /* ECCurve_NIST_K283 */
|
||||
&ecCurve_NIST_B283, /* ECCurve_NIST_B283 */
|
||||
&ecCurve_NIST_K409, /* ECCurve_NIST_K409 */
|
||||
&ecCurve_NIST_B409, /* ECCurve_NIST_B409 */
|
||||
&ecCurve_NIST_K571, /* ECCurve_NIST_K571 */
|
||||
&ecCurve_NIST_B571, /* ECCurve_NIST_B571 */
|
||||
&ecCurve_X9_62_PRIME_192V2, /* ECCurve_X9_62_PRIME_192V2 */
|
||||
&ecCurve_X9_62_PRIME_192V3, /* ECCurve_X9_62_PRIME_192V3 */
|
||||
&ecCurve_X9_62_PRIME_239V1, /* ECCurve_X9_62_PRIME_239V1 */
|
||||
&ecCurve_X9_62_PRIME_239V2, /* ECCurve_X9_62_PRIME_239V2 */
|
||||
&ecCurve_X9_62_PRIME_239V3, /* ECCurve_X9_62_PRIME_239V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V1, /* ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V2, /* ECCurve_X9_62_CHAR2_PNB163V2 */
|
||||
&ecCurve_X9_62_CHAR2_PNB163V3, /* ECCurve_X9_62_CHAR2_PNB163V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB176V1, /* ECCurve_X9_62_CHAR2_PNB176V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V1, /* ECCurve_X9_62_CHAR2_TNB191V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V2, /* ECCurve_X9_62_CHAR2_TNB191V2 */
|
||||
&ecCurve_X9_62_CHAR2_TNB191V3, /* ECCurve_X9_62_CHAR2_TNB191V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB208W1, /* ECCurve_X9_62_CHAR2_PNB208W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V1, /* ECCurve_X9_62_CHAR2_TNB239V1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V2, /* ECCurve_X9_62_CHAR2_TNB239V2 */
|
||||
&ecCurve_X9_62_CHAR2_TNB239V3, /* ECCurve_X9_62_CHAR2_TNB239V3 */
|
||||
&ecCurve_X9_62_CHAR2_PNB272W1, /* ECCurve_X9_62_CHAR2_PNB272W1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB304W1, /* ECCurve_X9_62_CHAR2_PNB304W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB359V1, /* ECCurve_X9_62_CHAR2_TNB359V1 */
|
||||
&ecCurve_X9_62_CHAR2_PNB368W1, /* ECCurve_X9_62_CHAR2_PNB368W1 */
|
||||
&ecCurve_X9_62_CHAR2_TNB431R1, /* ECCurve_X9_62_CHAR2_TNB431R1 */
|
||||
&ecCurve_SECG_PRIME_112R1, /* ECCurve_SECG_PRIME_112R1 */
|
||||
&ecCurve_SECG_PRIME_112R2, /* ECCurve_SECG_PRIME_112R2 */
|
||||
&ecCurve_SECG_PRIME_128R1, /* ECCurve_SECG_PRIME_128R1 */
|
||||
&ecCurve_SECG_PRIME_128R2, /* ECCurve_SECG_PRIME_128R2 */
|
||||
&ecCurve_SECG_PRIME_160K1, /* ECCurve_SECG_PRIME_160K1 */
|
||||
&ecCurve_SECG_PRIME_160R1, /* ECCurve_SECG_PRIME_160R1 */
|
||||
&ecCurve_SECG_PRIME_160R2, /* ECCurve_SECG_PRIME_160R2 */
|
||||
&ecCurve_SECG_PRIME_192K1, /* ECCurve_SECG_PRIME_192K1 */
|
||||
&ecCurve_SECG_PRIME_224K1, /* ECCurve_SECG_PRIME_224K1 */
|
||||
&ecCurve_SECG_PRIME_256K1, /* ECCurve_SECG_PRIME_256K1 */
|
||||
&ecCurve_SECG_CHAR2_113R1, /* ECCurve_SECG_CHAR2_113R1 */
|
||||
&ecCurve_SECG_CHAR2_113R2, /* ECCurve_SECG_CHAR2_113R2 */
|
||||
&ecCurve_SECG_CHAR2_131R1, /* ECCurve_SECG_CHAR2_131R1 */
|
||||
&ecCurve_SECG_CHAR2_131R2, /* ECCurve_SECG_CHAR2_131R2 */
|
||||
&ecCurve_SECG_CHAR2_163R1, /* ECCurve_SECG_CHAR2_163R1 */
|
||||
&ecCurve_SECG_CHAR2_193R1, /* ECCurve_SECG_CHAR2_193R1 */
|
||||
&ecCurve_SECG_CHAR2_193R2, /* ECCurve_SECG_CHAR2_193R2 */
|
||||
&ecCurve_SECG_CHAR2_239K1, /* ECCurve_SECG_CHAR2_239K1 */
|
||||
&ecCurve_WTLS_1, /* ECCurve_WTLS_1 */
|
||||
&ecCurve_WTLS_8, /* ECCurve_WTLS_8 */
|
||||
&ecCurve_WTLS_9, /* ECCurve_WTLS_9 */
|
||||
NULL /* ECCurve_pastLastCurve */
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_exp_h_
|
||||
#define __ecl_exp_h_
|
||||
|
||||
/* Curve field type */
|
||||
typedef enum {
|
||||
ECField_GFp,
|
||||
ECField_GF2m
|
||||
} ECField;
|
||||
|
||||
/* Hexadecimal encoding of curve parameters */
|
||||
struct ECCurveParamsStr {
|
||||
char *text;
|
||||
ECField field;
|
||||
unsigned int size;
|
||||
char *irr;
|
||||
char *curvea;
|
||||
char *curveb;
|
||||
char *genx;
|
||||
char *geny;
|
||||
char *order;
|
||||
int cofactor;
|
||||
};
|
||||
typedef struct ECCurveParamsStr ECCurveParams;
|
||||
|
||||
/* Named curve parameters */
|
||||
typedef enum {
|
||||
|
||||
ECCurve_noName = 0,
|
||||
|
||||
/* NIST prime curves */
|
||||
ECCurve_NIST_P192,
|
||||
ECCurve_NIST_P224,
|
||||
ECCurve_NIST_P256,
|
||||
ECCurve_NIST_P384,
|
||||
ECCurve_NIST_P521,
|
||||
|
||||
/* NIST binary curves */
|
||||
ECCurve_NIST_K163,
|
||||
ECCurve_NIST_B163,
|
||||
ECCurve_NIST_K233,
|
||||
ECCurve_NIST_B233,
|
||||
ECCurve_NIST_K283,
|
||||
ECCurve_NIST_B283,
|
||||
ECCurve_NIST_K409,
|
||||
ECCurve_NIST_B409,
|
||||
ECCurve_NIST_K571,
|
||||
ECCurve_NIST_B571,
|
||||
|
||||
/* ANSI X9.62 prime curves */
|
||||
/* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */
|
||||
ECCurve_X9_62_PRIME_192V2,
|
||||
ECCurve_X9_62_PRIME_192V3,
|
||||
ECCurve_X9_62_PRIME_239V1,
|
||||
ECCurve_X9_62_PRIME_239V2,
|
||||
ECCurve_X9_62_PRIME_239V3,
|
||||
/* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */
|
||||
|
||||
/* ANSI X9.62 binary curves */
|
||||
ECCurve_X9_62_CHAR2_PNB163V1,
|
||||
ECCurve_X9_62_CHAR2_PNB163V2,
|
||||
ECCurve_X9_62_CHAR2_PNB163V3,
|
||||
ECCurve_X9_62_CHAR2_PNB176V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V1,
|
||||
ECCurve_X9_62_CHAR2_TNB191V2,
|
||||
ECCurve_X9_62_CHAR2_TNB191V3,
|
||||
ECCurve_X9_62_CHAR2_PNB208W1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V1,
|
||||
ECCurve_X9_62_CHAR2_TNB239V2,
|
||||
ECCurve_X9_62_CHAR2_TNB239V3,
|
||||
ECCurve_X9_62_CHAR2_PNB272W1,
|
||||
ECCurve_X9_62_CHAR2_PNB304W1,
|
||||
ECCurve_X9_62_CHAR2_TNB359V1,
|
||||
ECCurve_X9_62_CHAR2_PNB368W1,
|
||||
ECCurve_X9_62_CHAR2_TNB431R1,
|
||||
|
||||
/* SEC2 prime curves */
|
||||
ECCurve_SECG_PRIME_112R1,
|
||||
ECCurve_SECG_PRIME_112R2,
|
||||
ECCurve_SECG_PRIME_128R1,
|
||||
ECCurve_SECG_PRIME_128R2,
|
||||
ECCurve_SECG_PRIME_160K1,
|
||||
ECCurve_SECG_PRIME_160R1,
|
||||
ECCurve_SECG_PRIME_160R2,
|
||||
ECCurve_SECG_PRIME_192K1,
|
||||
/* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */
|
||||
ECCurve_SECG_PRIME_224K1,
|
||||
/* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */
|
||||
ECCurve_SECG_PRIME_256K1,
|
||||
/* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */
|
||||
/* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */
|
||||
/* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */
|
||||
|
||||
/* SEC2 binary curves */
|
||||
ECCurve_SECG_CHAR2_113R1,
|
||||
ECCurve_SECG_CHAR2_113R2,
|
||||
ECCurve_SECG_CHAR2_131R1,
|
||||
ECCurve_SECG_CHAR2_131R2,
|
||||
/* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */
|
||||
ECCurve_SECG_CHAR2_163R1,
|
||||
/* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */
|
||||
ECCurve_SECG_CHAR2_193R1,
|
||||
ECCurve_SECG_CHAR2_193R2,
|
||||
/* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */
|
||||
ECCurve_SECG_CHAR2_239K1,
|
||||
/* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */
|
||||
/* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */
|
||||
/* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */
|
||||
/* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */
|
||||
/* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */
|
||||
/* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */
|
||||
|
||||
/* WTLS curves */
|
||||
ECCurve_WTLS_1,
|
||||
/* there is no WTLS 2 curve */
|
||||
/* ECCurve_WTLS_3 == ECCurve_NIST_K163 */
|
||||
/* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */
|
||||
/* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */
|
||||
/* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */
|
||||
/* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */
|
||||
ECCurve_WTLS_8,
|
||||
ECCurve_WTLS_9,
|
||||
/* ECCurve_WTLS_10 == ECCurve_NIST_K233 */
|
||||
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
|
||||
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
|
||||
|
||||
ECCurve_pastLastCurve
|
||||
} ECCurveName;
|
||||
|
||||
/* Aliased named curves */
|
||||
|
||||
#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192
|
||||
#define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192
|
||||
#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224
|
||||
#define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256
|
||||
#define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384
|
||||
#define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521
|
||||
#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163
|
||||
#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163
|
||||
#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233
|
||||
#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233
|
||||
#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283
|
||||
#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283
|
||||
#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409
|
||||
#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409
|
||||
#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571
|
||||
#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571
|
||||
#define ECCurve_WTLS_3 ECCurve_NIST_K163
|
||||
#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1
|
||||
#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1
|
||||
#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1
|
||||
#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1
|
||||
#define ECCurve_WTLS_10 ECCurve_NIST_K233
|
||||
#define ECCurve_WTLS_11 ECCurve_NIST_B233
|
||||
#define ECCurve_WTLS_12 ECCurve_NIST_P224
|
||||
|
||||
#endif /* __ecl_exp_h_ */
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com> and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecl_priv_h_
|
||||
#define __ecl_priv_h_
|
||||
|
||||
#include "ecl.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
|
||||
/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
|
||||
/* the following needs to go away... */
|
||||
#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
|
||||
#define ECL_SIXTY_FOUR_BIT
|
||||
#else
|
||||
#define ECL_THIRTY_TWO_BIT
|
||||
#endif
|
||||
|
||||
#define ECL_CURVE_DIGITS(curve_size_in_bits) \
|
||||
(((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
|
||||
#define ECL_BITS (sizeof(mp_digit)*8)
|
||||
#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
|
||||
|
||||
/* Gets the i'th bit in the binary representation of a. If i >= length(a),
|
||||
* then return 0. (The above behaviour differs from mpl_get_bit, which
|
||||
* causes an error if i >= length(a).) */
|
||||
#define MP_GET_BIT(a, i) \
|
||||
((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i))
|
||||
|
||||
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(cin)) + (a1) + (a2); \
|
||||
s = ACCUM(w); \
|
||||
cout = CARRYOUT(w); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_word w; \
|
||||
w = ((mp_word)(a1)) - (a2) - (bin); \
|
||||
s = ACCUM(w); \
|
||||
bout = (w >> MP_DIGIT_BIT) & 1; }
|
||||
|
||||
#else
|
||||
/* NOTE,
|
||||
* cin and cout could be the same variable.
|
||||
* bin and bout could be the same variable.
|
||||
* a1 or a2 and s could be the same variable.
|
||||
* don't trash those outputs until their respective inputs have
|
||||
* been read. */
|
||||
#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
|
||||
{ mp_digit tmp,sum; \
|
||||
tmp = (a1); \
|
||||
sum = tmp + (a2); \
|
||||
tmp = (sum < tmp); /* detect overflow */ \
|
||||
s = sum += (cin); \
|
||||
cout = tmp + (sum < (cin)); }
|
||||
|
||||
#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
|
||||
{ mp_digit tmp; \
|
||||
tmp = (a1); \
|
||||
s = tmp - (a2); \
|
||||
tmp = (s > tmp); /* detect borrow */ \
|
||||
if ((bin) && !s--) tmp++; \
|
||||
bout = tmp; }
|
||||
#endif
|
||||
|
||||
|
||||
struct GFMethodStr;
|
||||
typedef struct GFMethodStr GFMethod;
|
||||
struct GFMethodStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Irreducible that defines the field. For prime fields, this is the
|
||||
* prime p. For binary polynomial fields, this is the bitstring
|
||||
* representation of the irreducible polynomial. */
|
||||
mp_int irr;
|
||||
/* For prime fields, the value irr_arr[0] is the number of bits in the
|
||||
* field. For binary polynomial fields, the irreducible polynomial
|
||||
* f(t) is represented as an array of unsigned int[], where f(t) is
|
||||
* of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
|
||||
* > p[1] > ... > p[4] = 0. */
|
||||
unsigned int irr_arr[5];
|
||||
/* Field arithmetic methods. All methods (except field_enc and
|
||||
* field_dec) are assumed to take field-encoded parameters and return
|
||||
* field-encoded values. All methods (except field_enc and field_dec)
|
||||
* are required to be implemented. */
|
||||
mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (GFMethod *meth);
|
||||
};
|
||||
|
||||
/* Construct generic GFMethods. */
|
||||
GFMethod *GFMethod_consGFp(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGFp_mont(const mp_int *irr);
|
||||
GFMethod *GFMethod_consGF2m(const mp_int *irr,
|
||||
const unsigned int irr_arr[5]);
|
||||
/* Free the memory allocated (if any) to a GFMethod object. */
|
||||
void GFMethod_free(GFMethod *meth);
|
||||
|
||||
struct ECGroupStr {
|
||||
/* Indicates whether the structure was constructed from dynamic memory
|
||||
* or statically created. */
|
||||
int constructed;
|
||||
/* Field definition and arithmetic. */
|
||||
GFMethod *meth;
|
||||
/* Textual representation of curve name, if any. */
|
||||
char *text;
|
||||
/* Curve parameters, field-encoded. */
|
||||
mp_int curvea, curveb;
|
||||
/* x and y coordinates of the base point, field-encoded. */
|
||||
mp_int genx, geny;
|
||||
/* Order and cofactor of the base point. */
|
||||
mp_int order;
|
||||
int cofactor;
|
||||
/* Point arithmetic methods. All methods are assumed to take
|
||||
* field-encoded parameters and return field-encoded values. All
|
||||
* methods (except base_point_mul and points_mul) are required to be
|
||||
* implemented. */
|
||||
mp_err (*point_add) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_sub) (const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*point_mul) (const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
/* Extra storage for implementation-specific data. Any memory
|
||||
* allocated to these extra fields will be cleared by extra_free. */
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
void (*extra_free) (ECGroup *group);
|
||||
};
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* fixed length in-line adds. Count is in words */
|
||||
mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
/* Wrapper functions for generic binary polynomial field arithmetic. */
|
||||
mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
|
||||
/* Montgomery prime field arithmetic. */
|
||||
mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth);
|
||||
mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth);
|
||||
void ec_GFp_extra_free_mont(GFMethod *meth);
|
||||
|
||||
/* point multiplication */
|
||||
mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should
|
||||
* be an array of signed char's to output to, bitsize should be the number
|
||||
* of bits of out, in is the original scalar, and w is the window size.
|
||||
* NAF is discussed in the paper: D. Hankerson, J. Hernandez and A.
|
||||
* Menezes, "Software implementation of elliptic curve cryptography over
|
||||
* binary fields", Proc. CHES 2000. */
|
||||
mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in,
|
||||
int w);
|
||||
|
||||
/* Optimized field arithmetic */
|
||||
mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName);
|
||||
mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name);
|
||||
mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
|
||||
|
||||
/* Optimized floating-point arithmetic */
|
||||
#ifdef ECL_USE_FP
|
||||
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp192_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp224_fp(ECGroup *group);
|
||||
#endif
|
||||
|
||||
#endif /* __ecl_priv_h_ */
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ec2.h"
|
||||
#include "ecp.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Allocate memory for a new ECGroup object. */
|
||||
ECGroup *
|
||||
ECGroup_new()
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group;
|
||||
group = (ECGroup *) malloc(sizeof(ECGroup));
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
group->constructed = MP_YES;
|
||||
group->meth = NULL;
|
||||
group->text = NULL;
|
||||
MP_DIGITS(&group->curvea) = 0;
|
||||
MP_DIGITS(&group->curveb) = 0;
|
||||
MP_DIGITS(&group->genx) = 0;
|
||||
MP_DIGITS(&group->geny) = 0;
|
||||
MP_DIGITS(&group->order) = 0;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = NULL;
|
||||
group->validate_point = NULL;
|
||||
group->extra1 = NULL;
|
||||
group->extra2 = NULL;
|
||||
group->extra_free = NULL;
|
||||
MP_CHECKOK(mp_init(&group->curvea));
|
||||
MP_CHECKOK(mp_init(&group->curveb));
|
||||
MP_CHECKOK(mp_init(&group->genx));
|
||||
MP_CHECKOK(mp_init(&group->geny));
|
||||
MP_CHECKOK(mp_init(&group->order));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct a generic ECGroup for elliptic curves over prime fields with
|
||||
* field arithmetic implemented in Montgomery coordinates. */
|
||||
ECGroup *
|
||||
ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea,
|
||||
const mp_int *curveb, const mp_int *genx,
|
||||
const mp_int *geny, const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGFp_mont(irr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curvea, &group->curvea, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(curveb, &group->curveb, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GFp_pt_add_aff;
|
||||
group->point_sub = &ec_GFp_pt_sub_aff;
|
||||
group->point_dbl = &ec_GFp_pt_dbl_aff;
|
||||
group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_GFp_pts_mul_jac;
|
||||
group->validate_point = &ec_GFp_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
/* Construct a generic ECGroup for elliptic curves over binary polynomial
|
||||
* fields. */
|
||||
ECGroup *
|
||||
ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
|
||||
const mp_int *curvea, const mp_int *curveb,
|
||||
const mp_int *genx, const mp_int *geny,
|
||||
const mp_int *order, int cofactor)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ECGroup *group = NULL;
|
||||
|
||||
group = ECGroup_new();
|
||||
if (group == NULL)
|
||||
return NULL;
|
||||
|
||||
group->meth = GFMethod_consGF2m(irr, irr_arr);
|
||||
if (group->meth == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_copy(curvea, &group->curvea));
|
||||
MP_CHECKOK(mp_copy(curveb, &group->curveb));
|
||||
MP_CHECKOK(mp_copy(genx, &group->genx));
|
||||
MP_CHECKOK(mp_copy(geny, &group->geny));
|
||||
MP_CHECKOK(mp_copy(order, &group->order));
|
||||
group->cofactor = cofactor;
|
||||
group->point_add = &ec_GF2m_pt_add_aff;
|
||||
group->point_sub = &ec_GF2m_pt_sub_aff;
|
||||
group->point_dbl = &ec_GF2m_pt_dbl_aff;
|
||||
group->point_mul = &ec_GF2m_pt_mul_mont;
|
||||
group->base_point_mul = NULL;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->validate_point = &ec_GF2m_validate_point;
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Construct ECGroup from hex parameters and name, if any. Called by
|
||||
* ECGroup_fromHex and ECGroup_fromName. */
|
||||
ECGroup *
|
||||
ecgroup_fromNameAndHex(const ECCurveName name,
|
||||
const ECCurveParams * params)
|
||||
{
|
||||
mp_int irr, curvea, curveb, genx, geny, order;
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* initialize values */
|
||||
MP_DIGITS(&irr) = 0;
|
||||
MP_DIGITS(&curvea) = 0;
|
||||
MP_DIGITS(&curveb) = 0;
|
||||
MP_DIGITS(&genx) = 0;
|
||||
MP_DIGITS(&geny) = 0;
|
||||
MP_DIGITS(&order) = 0;
|
||||
MP_CHECKOK(mp_init(&irr));
|
||||
MP_CHECKOK(mp_init(&curvea));
|
||||
MP_CHECKOK(mp_init(&curveb));
|
||||
MP_CHECKOK(mp_init(&genx));
|
||||
MP_CHECKOK(mp_init(&geny));
|
||||
MP_CHECKOK(mp_init(&order));
|
||||
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
|
||||
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
|
||||
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
|
||||
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (params->field == ECField_GFp) {
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
switch (name) {
|
||||
#ifdef ECL_USE_FP
|
||||
case ECCurve_SECG_PRIME_160R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_secp160r1_fp(group));
|
||||
break;
|
||||
#endif
|
||||
case ECCurve_SECG_PRIME_192R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp192_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp192(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_224R1:
|
||||
#ifdef ECL_USE_FP
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_nistp224_fp(group));
|
||||
#else
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp224(group, name));
|
||||
#endif
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
#endif
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
#ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
}
|
||||
} else if (params->field == ECField_GF2m) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
if ((name == ECCurve_NIST_K163) ||
|
||||
(name == ECCurve_NIST_B163) ||
|
||||
(name == ECCurve_SECG_CHAR2_163R1)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m163(group, name));
|
||||
} else if ((name == ECCurve_SECG_CHAR2_193R1) ||
|
||||
(name == ECCurve_SECG_CHAR2_193R2)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m193(group, name));
|
||||
} else if ((name == ECCurve_NIST_K233) ||
|
||||
(name == ECCurve_NIST_B233)) {
|
||||
MP_CHECKOK(ec_group_set_gf2m233(group, name));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (params->text != NULL)) {
|
||||
group->text = strdup(params->text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&irr);
|
||||
mp_clear(&curvea);
|
||||
mp_clear(&curveb);
|
||||
mp_clear(&genx);
|
||||
mp_clear(&geny);
|
||||
mp_clear(&order);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromHex(const ECCurveParams * params)
|
||||
{
|
||||
return ecgroup_fromNameAndHex(ECCurve_noName, params);
|
||||
}
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromName(const ECCurveName name)
|
||||
{
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
params = EC_GetNamedCurveParams(name);
|
||||
if (params == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* construct actual group */
|
||||
group = ecgroup_fromNameAndHex(name, params);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py)
|
||||
{
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
return group->validate_point(px, py, group);
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECGroup object. */
|
||||
void
|
||||
ECGroup_free(ECGroup *group)
|
||||
{
|
||||
if (group == NULL)
|
||||
return;
|
||||
GFMethod_free(group->meth);
|
||||
if (group->constructed == MP_NO)
|
||||
return;
|
||||
mp_clear(&group->curvea);
|
||||
mp_clear(&group->curveb);
|
||||
mp_clear(&group->genx);
|
||||
mp_clear(&group->geny);
|
||||
mp_clear(&group->order);
|
||||
if (group->text != NULL)
|
||||
free(group->text);
|
||||
if (group->extra_free != NULL)
|
||||
group->extra_free(group);
|
||||
free(group);
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Although this is not an exported header file, code which uses elliptic
|
||||
* curve point operations will need to include it. */
|
||||
|
||||
#ifndef __ecl_h_
|
||||
#define __ecl_h_
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include "mpi.h"
|
||||
|
||||
struct ECGroupStr;
|
||||
typedef struct ECGroupStr ECGroup;
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *ECGroup_fromHex(const ECCurveParams * params);
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *ECGroup_fromName(const ECCurveName name);
|
||||
|
||||
/* Free an allocated ECGroup. */
|
||||
void ECGroup_free(ECGroup *group);
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *ECCurveParams_dup(const ECCurveParams * params);
|
||||
|
||||
/* Free an allocated ECCurveParams */
|
||||
void EC_FreeCurveParams(ECCurveParams * params);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Input and output values are assumed to
|
||||
* be NOT field-encoded. */
|
||||
mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
|
||||
const mp_int *k2, const mp_int *px, const mp_int *py,
|
||||
mp_int *qx, mp_int *qy);
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62.
|
||||
* Returns MP_YES if the public key is valid, MP_NO if the public key
|
||||
* is invalid, or an error code if the validation could not be
|
||||
* performed. */
|
||||
mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
|
||||
mp_int *py);
|
||||
|
||||
#endif /* __ecl_h_ */
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; }
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *
|
||||
ECCurveParams_dup(const ECCurveParams * params)
|
||||
{
|
||||
int res = 1;
|
||||
ECCurveParams *ret = NULL;
|
||||
|
||||
CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams)));
|
||||
if (params->text != NULL) {
|
||||
CHECK(ret->text = strdup(params->text));
|
||||
}
|
||||
ret->field = params->field;
|
||||
ret->size = params->size;
|
||||
if (params->irr != NULL) {
|
||||
CHECK(ret->irr = strdup(params->irr));
|
||||
}
|
||||
if (params->curvea != NULL) {
|
||||
CHECK(ret->curvea = strdup(params->curvea));
|
||||
}
|
||||
if (params->curveb != NULL) {
|
||||
CHECK(ret->curveb = strdup(params->curveb));
|
||||
}
|
||||
if (params->genx != NULL) {
|
||||
CHECK(ret->genx = strdup(params->genx));
|
||||
}
|
||||
if (params->geny != NULL) {
|
||||
CHECK(ret->geny = strdup(params->geny));
|
||||
}
|
||||
if (params->order != NULL) {
|
||||
CHECK(ret->order = strdup(params->order));
|
||||
}
|
||||
ret->cofactor = params->cofactor;
|
||||
|
||||
CLEANUP:
|
||||
if (res != 1) {
|
||||
EC_FreeCurveParams(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *
|
||||
EC_GetNamedCurveParams(const ECCurveName name)
|
||||
{
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ECCurveParams_dup(ecCurve_map[name]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECCurveParams object. */
|
||||
void
|
||||
EC_FreeCurveParams(ECCurveParams * params)
|
||||
{
|
||||
if (params == NULL)
|
||||
return;
|
||||
if (params->text != NULL)
|
||||
free(params->text);
|
||||
if (params->irr != NULL)
|
||||
free(params->irr);
|
||||
if (params->curvea != NULL)
|
||||
free(params->curvea);
|
||||
if (params->curveb != NULL)
|
||||
free(params->curveb);
|
||||
if (params->genx != NULL)
|
||||
free(params->genx);
|
||||
if (params->geny != NULL)
|
||||
free(params->geny);
|
||||
if (params->order != NULL)
|
||||
free(params->order);
|
||||
free(params);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
* are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int kt;
|
||||
|
||||
ARGCHK((k != NULL) && (group != NULL), MP_BADARG);
|
||||
MP_DIGITS(&kt) = 0;
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (mp_cmp(k, &group->order) > 0) {
|
||||
MP_CHECKOK(mp_init(&kt));
|
||||
MP_CHECKOK(mp_mod(k, &group->order, &kt));
|
||||
} else {
|
||||
MP_SIGN(&kt) = MP_ZPOS;
|
||||
MP_USED(&kt) = MP_USED(k);
|
||||
MP_ALLOC(&kt) = MP_ALLOC(k);
|
||||
MP_DIGITS(&kt) = MP_DIGITS(k);
|
||||
}
|
||||
|
||||
if ((px == NULL) || (py == NULL)) {
|
||||
if (group->base_point_mul) {
|
||||
MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->
|
||||
point_mul(&kt, &group->genx, &group->geny, rx, ry,
|
||||
group));
|
||||
}
|
||||
} else {
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
|
||||
MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group));
|
||||
} else {
|
||||
MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group));
|
||||
}
|
||||
}
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (MP_DIGITS(&kt) != MP_DIGITS(k)) {
|
||||
mp_clear(&kt);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
|
||||
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));
|
||||
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. Uses
|
||||
* algorithm 15 (simultaneous multiple point multiplication) from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST
|
||||
* Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][0],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
MP_CHECKOK( mp_init_size(&precomp[i][j][1],
|
||||
ECL_MAX_FIELD_SIZE_DIGITS) );
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(group->
|
||||
point_add(rx, ry, &precomp[ai][bi][0],
|
||||
&precomp[ai][bi][1], rx, ry, group));
|
||||
}
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Input and output values are assumed to be NOT field-encoded. */
|
||||
mp_err
|
||||
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
|
||||
const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k1t, k2t;
|
||||
const mp_int *k1p, *k2p;
|
||||
|
||||
MP_DIGITS(&k1t) = 0;
|
||||
MP_DIGITS(&k2t) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
|
||||
/* want scalar to be less than or equal to group order */
|
||||
if (k1 != NULL) {
|
||||
if (mp_cmp(k1, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k1t));
|
||||
MP_CHECKOK(mp_mod(k1, &group->order, &k1t));
|
||||
k1p = &k1t;
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
} else {
|
||||
k1p = k1;
|
||||
}
|
||||
if (k2 != NULL) {
|
||||
if (mp_cmp(k2, &group->order) >= 0) {
|
||||
MP_CHECKOK(mp_init(&k2t));
|
||||
MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
|
||||
k2p = &k2t;
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
} else {
|
||||
k2p = k2;
|
||||
}
|
||||
|
||||
/* if points_mul is defined, then use it */
|
||||
if (group->points_mul) {
|
||||
res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
|
||||
} else {
|
||||
res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k1t);
|
||||
mp_clear(&k2t);
|
||||
return res;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_h_
|
||||
#define __ecp_h_
|
||||
|
||||
#include "ecl-priv.h"
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py);
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
|
||||
* qy). Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = P - Q. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group);
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses affine coordinates. */
|
||||
mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). */
|
||||
mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). */
|
||||
mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz);
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz);
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, qz). Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
/* Computes R = 2P. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py,
|
||||
const mp_int *pz, mp_int *rx, mp_int *ry,
|
||||
mp_int *rz, const ECGroup *group);
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Uses Jacobian coordinates. */
|
||||
mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
#endif
|
||||
|
||||
/* Computes R(x, y) = k1 * G + k2 * P(x, y), where G is the generator
|
||||
* (base point) of the group of points on the elliptic curve. Allows k1 =
|
||||
* NULL or { k2, P } = NULL. Implemented using mixed Jacobian-affine
|
||||
* coordinates. Input and output values are assumed to be NOT
|
||||
* field-encoded and are in affine form. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
#endif /* __ecp_h_ */
|
||||
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP192_DIGITS ECL_CURVE_DIGITS(192)
|
||||
|
||||
/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
mp_digit r3;
|
||||
#ifndef MPI_AMD64_ADD
|
||||
mp_digit carry;
|
||||
#endif
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
|
||||
#else
|
||||
mp_digit a5 = 0, a4 = 0, a3 = 0;
|
||||
mp_digit r0, r1, r2;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP192_DIGITS) {
|
||||
if (a == r) {
|
||||
return MP_OKAY;
|
||||
}
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECP192_DIGITS*2) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
/* copy out upper words of a */
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
|
||||
/* in all the math below,
|
||||
* nXb is most signifiant, nXa is least significant */
|
||||
switch (a_used) {
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
case 7:
|
||||
a3a = MP_DIGIT(a, 6);
|
||||
}
|
||||
|
||||
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
MP_ADD_CARRY(r0a, a3a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
|
||||
r3 = carry; carry = 0;
|
||||
MP_ADD_CARRY(r0a, a5a, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1a, a4a, r1a, 0, carry);
|
||||
MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
MP_ADD_CARRY(r0a, r3, r0a, 0, carry);
|
||||
MP_ADD_CARRY(r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
|
||||
MP_ADD_CARRY(r1b, 0, r1b, carry, carry);
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
r3 = carry;
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
|
||||
&& (r1b == 0xffffffff) ) &&
|
||||
((r1a == 0xffffffff) ||
|
||||
(r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
|
||||
(r0b == 0xffffffff)) ) {
|
||||
/* do a quick subtract */
|
||||
MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
|
||||
r0b += carry;
|
||||
r1a = r1b = r2a = r2b = 0;
|
||||
}
|
||||
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 6));
|
||||
}
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
MP_USED(r) = 6;
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
case 4:
|
||||
a3 = MP_DIGIT(a, 3);
|
||||
}
|
||||
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, a3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a4, r2, carry, carry);
|
||||
r3 = carry;
|
||||
MP_ADD_CARRY(r0, a5, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a5, r2, carry, carry);
|
||||
r3 += carry;
|
||||
MP_ADD_CARRY(r1, a4, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 += carry;
|
||||
|
||||
#else
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* set the lower words of r */
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq %5,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %6,%0 \n\t"
|
||||
"adcq %6,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
"addq %5,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
|
||||
"=r"(a4), "=r"(a5)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3),
|
||||
"4" (a3), "5" (a4), "6"(a5)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* reduce out the carry */
|
||||
while (r3) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, r3, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, r3, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
r3 = carry;
|
||||
#else
|
||||
a3=r3;
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %4,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
|
||||
: "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check for final reduction */
|
||||
/*
|
||||
* our field is 0xffffffffffffffff, 0xfffffffffffffffe,
|
||||
* 0xffffffffffffffff. That means we can only be over and need
|
||||
* one more reduction
|
||||
* if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
|
||||
* and
|
||||
* r1 == 0xffffffffffffffffff or
|
||||
* r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
|
||||
* In all cases, we subtract the field (or add the 2's
|
||||
* complement value (1,1,0)). (r0, r1, r2)
|
||||
*/
|
||||
if (r3 || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
/* do a quick subtract */
|
||||
r0++;
|
||||
r1 = r2 = 0;
|
||||
}
|
||||
/* set the lower words of r */
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
}
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_USED(r) = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
/* Compute the sum of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit a0 = 0, a1 = 0, a2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit carry;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
a2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
a1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
a0 = MP_DIGIT(a,0);
|
||||
}
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(a0, r0, r0, 0, carry);
|
||||
MP_ADD_CARRY(a1, r1, r1, carry, carry);
|
||||
MP_ADD_CARRY(a2, r2, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"addq %4,%0 \n\t"
|
||||
"adcq %5,%1 \n\t"
|
||||
"adcq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
|
||||
: "r" (a0), "r" (a1), "r" (a2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'subract' if we've gone over
|
||||
* (add the 2's complement of the curve field) */
|
||||
if (carry || ((r2 == MP_DIGIT_MAX) &&
|
||||
((r1 == MP_DIGIT_MAX) ||
|
||||
((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_ADD_CARRY(r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 1, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
#else
|
||||
__asm__ (
|
||||
"addq $1,%0 \n\t"
|
||||
"adcq $1,%1 \n\t"
|
||||
"adcq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the diff of 192 bit curves. Do the work in-line since the
|
||||
* number of words are so small, we don't want to overhead of mp function
|
||||
* calls. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_digit b0 = 0, b1 = 0, b2 = 0;
|
||||
mp_digit r0 = 0, r1 = 0, r2 = 0;
|
||||
mp_digit borrow;
|
||||
|
||||
switch(MP_USED(a)) {
|
||||
case 3:
|
||||
r2 = MP_DIGIT(a,2);
|
||||
case 2:
|
||||
r1 = MP_DIGIT(a,1);
|
||||
case 1:
|
||||
r0 = MP_DIGIT(a,0);
|
||||
}
|
||||
|
||||
switch(MP_USED(b)) {
|
||||
case 3:
|
||||
b2 = MP_DIGIT(b,2);
|
||||
case 2:
|
||||
b1 = MP_DIGIT(b,1);
|
||||
case 1:
|
||||
b0 = MP_DIGIT(b,0);
|
||||
}
|
||||
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, b0, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"xorq %3,%3 \n\t"
|
||||
"subq %4,%0 \n\t"
|
||||
"sbbq %5,%1 \n\t"
|
||||
"sbbq %6,%2 \n\t"
|
||||
"adcq $0,%3 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
|
||||
: "r" (b0), "r" (b1), "r" (b2), "0" (r0),
|
||||
"1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
|
||||
/* Do quick 'add' if we've gone under 0
|
||||
* (subtract the 2's complement of the curve field) */
|
||||
if (borrow) {
|
||||
#ifndef MPI_AMD64_ADD
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, borrow);
|
||||
MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
|
||||
MP_SUB_BORROW(r2, 0, r2, borrow, borrow);
|
||||
#else
|
||||
__asm__ (
|
||||
"subq $1,%0 \n\t"
|
||||
"sbbq $1,%1 \n\t"
|
||||
"sbbq $0,%2 \n\t"
|
||||
: "=r"(r0), "=r"(r1), "=r"(r2)
|
||||
: "0" (r0), "1" (r1), "2" (r2)
|
||||
: "%cc" );
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_CHECKOK(s_mp_pad(r, 3));
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 3;
|
||||
s_mp_clamp(r);
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p192. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p192.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p192.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p192. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp192(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P192) {
|
||||
group->meth->field_mod = &ec_GFp_nistp192_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp192_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp192_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp192_div;
|
||||
#ifndef ECL_THIRTY_TWO_BIT
|
||||
group->meth->field_add = &ec_GFp_nistp192_add;
|
||||
group->meth->field_sub = &ec_GFp_nistp192_sub;
|
||||
#endif
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
|
||||
|
||||
/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
|
||||
* algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
|
||||
int r3b;
|
||||
mp_digit carry;
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a6a = 0, a6b = 0,
|
||||
a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
|
||||
mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
|
||||
#else
|
||||
mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
|
||||
mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
#endif
|
||||
|
||||
/* reduction not needed if a is not larger than field size */
|
||||
if (a_used < ECP224_DIGITS) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size, use regular
|
||||
* reduction */
|
||||
if (a_used > ECL_CURVE_DIGITS(224*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 14:
|
||||
a6b = MP_DIGIT(a, 13);
|
||||
case 13:
|
||||
a6a = MP_DIGIT(a, 12);
|
||||
case 12:
|
||||
a5b = MP_DIGIT(a, 11);
|
||||
case 11:
|
||||
a5a = MP_DIGIT(a, 10);
|
||||
case 10:
|
||||
a4b = MP_DIGIT(a, 9);
|
||||
case 9:
|
||||
a4a = MP_DIGIT(a, 8);
|
||||
case 8:
|
||||
a3b = MP_DIGIT(a, 7);
|
||||
}
|
||||
r3a = MP_DIGIT(a, 6);
|
||||
r2b= MP_DIGIT(a, 5);
|
||||
r2a= MP_DIGIT(a, 4);
|
||||
r1b = MP_DIGIT(a, 3);
|
||||
r1a = MP_DIGIT(a, 2);
|
||||
r0b = MP_DIGIT(a, 1);
|
||||
r0a = MP_DIGIT(a, 0);
|
||||
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
|
||||
r3b = carry;
|
||||
MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
|
||||
MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
r3b -= carry;
|
||||
}
|
||||
|
||||
while (r3b > 0) {
|
||||
int tmp;
|
||||
MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
|
||||
MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
|
||||
MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
|
||||
}
|
||||
tmp = carry;
|
||||
MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
|
||||
MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
|
||||
MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
|
||||
MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
|
||||
tmp -= carry;
|
||||
}
|
||||
r3b = tmp;
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
mp_digit maxInt = MP_DIGIT_MAX;
|
||||
MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
|
||||
MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
|
||||
MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
|
||||
MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
|
||||
MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
|
||||
MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
|
||||
MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
|
||||
r3b += carry;
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
|
||||
&& (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
|
||||
((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
|
||||
MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
|
||||
MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
|
||||
r1b = r2a = r2b = r3a = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 7));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 7;
|
||||
MP_DIGIT(r, 6) = r3a;
|
||||
MP_DIGIT(r, 5) = r2b;
|
||||
MP_DIGIT(r, 4) = r2a;
|
||||
MP_DIGIT(r, 3) = r1b;
|
||||
MP_DIGIT(r, 2) = r1a;
|
||||
MP_DIGIT(r, 1) = r0b;
|
||||
MP_DIGIT(r, 0) = r0a;
|
||||
#else
|
||||
/* copy out upper words of a */
|
||||
switch (a_used) {
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a, 6);
|
||||
a6b = a6 >> 32;
|
||||
a6a_a5b = a6 << 32;
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a, 5);
|
||||
a5b = a5 >> 32;
|
||||
a6a_a5b |= a5b;
|
||||
a5b = a5b << 32;
|
||||
a5a_a4b = a5 << 32;
|
||||
a5a = a5 & 0xffffffff;
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a, 4);
|
||||
a5a_a4b |= a4 >> 32;
|
||||
a4a_a3b = a4 << 32;
|
||||
case 4:
|
||||
a3b = MP_DIGIT(a, 3) >> 32;
|
||||
a4a_a3b |= a3b;
|
||||
a3b = a3b << 32;
|
||||
}
|
||||
|
||||
r3 = MP_DIGIT(a, 3) & 0xffffffff;
|
||||
r2 = MP_DIGIT(a, 2);
|
||||
r1 = MP_DIGIT(a, 1);
|
||||
r0 = MP_DIGIT(a, 0);
|
||||
|
||||
/* implement r = (a3a,a2,a1,a0)
|
||||
+(a5a, a4,a3b, 0)
|
||||
+( 0, a6,a5b, 0)
|
||||
-( 0 0, 0|a6b, a6a|a5b )
|
||||
-( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
|
||||
MP_ADD_CARRY (r1, a3b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a4 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, a5a, r3, carry, carry);
|
||||
MP_ADD_CARRY (r1, a5b, r1, 0, carry);
|
||||
MP_ADD_CARRY (r2, a6 , r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, 0, r3, carry, carry);
|
||||
|
||||
MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6b , r3, carry, carry);
|
||||
MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6b , r1, carry, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
|
||||
|
||||
/* if the value is negative, r3 has a 2's complement
|
||||
* high value */
|
||||
r3b = (int)(r3 >>32);
|
||||
while (r3b > 0) {
|
||||
r3 &= 0xffffffff;
|
||||
MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry);
|
||||
if (carry) {
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, 0, r3, carry, carry);
|
||||
}
|
||||
MP_SUB_BORROW(r0, r3b, r0, 0, carry);
|
||||
if (carry) {
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
}
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
|
||||
while (r3b < 0) {
|
||||
MP_ADD_CARRY (r0, 1, r0, 0, carry);
|
||||
MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
|
||||
MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
|
||||
r3b = (int)(r3 >>32);
|
||||
}
|
||||
/* check for final reduction */
|
||||
/* now the only way we are over is if the top 4 words are all ones */
|
||||
if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
|
||||
&& ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
|
||||
((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
|
||||
/* one last subraction */
|
||||
MP_SUB_BORROW(r0, 1, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
r2 = r3 = 0;
|
||||
}
|
||||
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r, 4));
|
||||
}
|
||||
/* set the lower words of r */
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
MP_DIGIT(r, 3) = r3;
|
||||
MP_DIGIT(r, 2) = r2;
|
||||
MP_DIGIT(r, 1) = r1;
|
||||
MP_DIGIT(r, 0) = r0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p224. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p224.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p224.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p224. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp224(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P224) {
|
||||
group->meth->field_mod = &ec_GFp_nistp224_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp224_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp224_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp224_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r.
|
||||
* Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_size a_used = MP_USED(a);
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
mp_digit carry;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0;
|
||||
mp_digit r0, r1, r2, r3, r4, r5, r6, r7;
|
||||
int r8; /* must be a signed value ! */
|
||||
#else
|
||||
mp_digit a4=0, a5=0, a6=0, a7=0;
|
||||
mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l;
|
||||
mp_digit r0, r1, r2, r3;
|
||||
int r4; /* must be a signed value ! */
|
||||
#endif
|
||||
/* for polynomials larger than twice the field size
|
||||
* use regular reduction */
|
||||
if (a_bits < 256) {
|
||||
if (a == r) return MP_OKAY;
|
||||
return mp_copy(a,r);
|
||||
}
|
||||
if (a_bits > 512) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
switch (a_used) {
|
||||
case 16:
|
||||
a15 = MP_DIGIT(a,15);
|
||||
case 15:
|
||||
a14 = MP_DIGIT(a,14);
|
||||
case 14:
|
||||
a13 = MP_DIGIT(a,13);
|
||||
case 13:
|
||||
a12 = MP_DIGIT(a,12);
|
||||
case 12:
|
||||
a11 = MP_DIGIT(a,11);
|
||||
case 11:
|
||||
a10 = MP_DIGIT(a,10);
|
||||
case 10:
|
||||
a9 = MP_DIGIT(a,9);
|
||||
case 9:
|
||||
a8 = MP_DIGIT(a,8);
|
||||
}
|
||||
|
||||
r0 = MP_DIGIT(a,0);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r4 = MP_DIGIT(a,4);
|
||||
r5 = MP_DIGIT(a,5);
|
||||
r6 = MP_DIGIT(a,6);
|
||||
r7 = MP_DIGIT(a,7);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 = carry;
|
||||
MP_ADD_CARRY(r3, a11, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a12, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a13, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a14, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r3, a12, r3, 0, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* combine last bottom of sum 3 with second sum 2 */
|
||||
MP_ADD_CARRY(r0, a8, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a9, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a10, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a12, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a13, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a14, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a15, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a15, r7, carry, carry); /* from sum 3 */
|
||||
r8 += carry;
|
||||
/* sum 3 (rest of it)*/
|
||||
MP_ADD_CARRY(r6, a14, r6, 0, carry);
|
||||
MP_ADD_CARRY(r7, 0, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* sum 4 (rest of it)*/
|
||||
MP_ADD_CARRY(r0, a9, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a10, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a11, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a13, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, a14, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, a15, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, a13, r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, a8, r7, carry, carry);
|
||||
r8 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a11, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a12, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a13, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, 0, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a8, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a10, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a12, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a13, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a14, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a15, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, 0, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, 0, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, a9, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a11, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a13, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a14, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a15, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a8, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a9, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a10, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a12, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a14, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a15, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a9, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, a10, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, a11, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, 0, r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, a13, r7, carry, carry);
|
||||
r8 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r8 > 0) {
|
||||
mp_digit r8_d = r8;
|
||||
MP_ADD_CARRY(r0, r8_d, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, 0, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, -r8_d, r3, carry, carry);
|
||||
MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_ADD_CARRY(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_ADD_CARRY(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r8 < 0) {
|
||||
mp_digit r8_d = -r8;
|
||||
MP_SUB_BORROW(r0, r8_d, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, 0, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, -r8_d, r3, carry, carry);
|
||||
MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry, carry);
|
||||
MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry, carry);
|
||||
MP_SUB_BORROW(r6, -(r8_d+1), r6, carry, carry);
|
||||
MP_SUB_BORROW(r7, (r8_d-1), r7, carry, carry);
|
||||
r8 = -carry;
|
||||
}
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,8));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 8;
|
||||
|
||||
MP_DIGIT(r,7) = r7;
|
||||
MP_DIGIT(r,6) = r6;
|
||||
MP_DIGIT(r,5) = r5;
|
||||
MP_DIGIT(r,4) = r4;
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r7 == MP_DIGIT_MAX) &&
|
||||
((r6 > 1) || ((r6 == 1) &&
|
||||
(r5 || r4 || r3 ||
|
||||
((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX)
|
||||
&& (r0 == MP_DIGIT_MAX)))))) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
#ifdef notdef
|
||||
|
||||
|
||||
/* smooth the negatives */
|
||||
while (MP_SIGN(r) != MP_ZPOS) {
|
||||
MP_CHECKOK(mp_add(r, &meth->irr, r));
|
||||
}
|
||||
while (MP_USED(r) > 8) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
/* final reduction if necessary */
|
||||
if (MP_DIGIT(r,7) >= MP_DIGIT(&meth->irr,7)) {
|
||||
if (mp_cmp(r,&meth->irr) != MP_LT) {
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s_mp_clamp(r);
|
||||
#else
|
||||
switch (a_used) {
|
||||
case 8:
|
||||
a7 = MP_DIGIT(a,7);
|
||||
case 7:
|
||||
a6 = MP_DIGIT(a,6);
|
||||
case 6:
|
||||
a5 = MP_DIGIT(a,5);
|
||||
case 5:
|
||||
a4 = MP_DIGIT(a,4);
|
||||
}
|
||||
a7l = a7 << 32;
|
||||
a7h = a7 >> 32;
|
||||
a6l = a6 << 32;
|
||||
a6h = a6 >> 32;
|
||||
a5l = a5 << 32;
|
||||
a5h = a5 >> 32;
|
||||
a4l = a4 << 32;
|
||||
a4h = a4 >> 32;
|
||||
r3 = MP_DIGIT(a,3);
|
||||
r2 = MP_DIGIT(a,2);
|
||||
r1 = MP_DIGIT(a,1);
|
||||
r0 = MP_DIGIT(a,0);
|
||||
|
||||
/* sum 1 */
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 = carry;
|
||||
MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 2 */
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
MP_ADD_CARRY(r1, a6l, r1, 0, carry);
|
||||
MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7h, r3, carry, carry);
|
||||
r4 += carry;
|
||||
|
||||
/* sum 3 */
|
||||
MP_ADD_CARRY(r0, a4, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, 0, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a7, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* sum 4 */
|
||||
MP_ADD_CARRY(r0, a4h | a5l, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, a7, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry);
|
||||
r4 += carry;
|
||||
/* diff 5 */
|
||||
MP_SUB_BORROW(r0, a5h | a6l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a6h, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 6 */
|
||||
MP_SUB_BORROW(r0, a6, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, 0, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 7 */
|
||||
MP_SUB_BORROW(r0, a6h|a7l, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a7h|a4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a4h|a5l, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6l, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
/* diff 8 */
|
||||
MP_SUB_BORROW(r0, a7, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, a4h<<32, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, a5, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, a6h<<32, r3, carry, carry);
|
||||
r4 -= carry;
|
||||
|
||||
/* reduce the overflows */
|
||||
while (r4 > 0) {
|
||||
mp_digit r4_long = r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_ADD_CARRY(r0, r4_long, r0, 0, carry);
|
||||
MP_ADD_CARRY(r1, -r4l, r1, carry, carry);
|
||||
MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = carry;
|
||||
}
|
||||
|
||||
/* reduce the underflows */
|
||||
while (r4 < 0) {
|
||||
mp_digit r4_long = -r4;
|
||||
mp_digit r4l = (r4_long << 32);
|
||||
MP_SUB_BORROW(r0, r4_long, r0, 0, carry);
|
||||
MP_SUB_BORROW(r1, -r4l, r1, carry, carry);
|
||||
MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry, carry);
|
||||
MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry, carry);
|
||||
r4 = -carry;
|
||||
}
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(s_mp_pad(r,4));
|
||||
}
|
||||
MP_SIGN(r) = MP_ZPOS;
|
||||
MP_USED(r) = 4;
|
||||
|
||||
MP_DIGIT(r,3) = r3;
|
||||
MP_DIGIT(r,2) = r2;
|
||||
MP_DIGIT(r,1) = r1;
|
||||
MP_DIGIT(r,0) = r0;
|
||||
|
||||
/* final reduction if necessary */
|
||||
if ((r3 > 0xFFFFFFFF00000001ULL) ||
|
||||
((r3 == 0xFFFFFFFF00000001ULL) &&
|
||||
(r2 || (r1 >> 32)||
|
||||
(r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) {
|
||||
/* very rare, just use mp_sub */
|
||||
MP_CHECKOK(mp_sub(r, &meth->irr, r));
|
||||
}
|
||||
|
||||
s_mp_clamp(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p256. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p256.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p256.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p256. */
|
||||
mp_err
|
||||
ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp256(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P256) {
|
||||
group->meth->field_mod = &ec_GFp_nistp256_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp256_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp256_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r.
|
||||
* Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m[10];
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
mp_digit s[10][12];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 12;
|
||||
MP_USED(&m[i]) = 12;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#else
|
||||
mp_digit s[10][6];
|
||||
for (i = 0; i < 10; i++) {
|
||||
MP_SIGN(&m[i]) = MP_ZPOS;
|
||||
MP_ALLOC(&m[i]) = 6;
|
||||
MP_USED(&m[i]) = 6;
|
||||
MP_DIGITS(&m[i]) = s[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = 0;
|
||||
s[1][3] = 0;
|
||||
s[1][4] = MP_DIGIT(a, 21);
|
||||
s[1][5] = MP_DIGIT(a, 22);
|
||||
s[1][6] = MP_DIGIT(a, 23);
|
||||
s[1][7] = 0;
|
||||
s[1][8] = 0;
|
||||
s[1][9] = 0;
|
||||
s[1][10] = 0;
|
||||
s[1][11] = 0;
|
||||
for (i = 0; i < 12; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+12);
|
||||
}
|
||||
s[3][0] = MP_DIGIT(a, 21);
|
||||
s[3][1] = MP_DIGIT(a, 22);
|
||||
s[3][2] = MP_DIGIT(a, 23);
|
||||
for (i = 3; i < 12; i++) {
|
||||
s[3][i] = MP_DIGIT(a, i+9);
|
||||
}
|
||||
s[4][0] = 0;
|
||||
s[4][1] = MP_DIGIT(a, 23);
|
||||
s[4][2] = 0;
|
||||
s[4][3] = MP_DIGIT(a, 20);
|
||||
for (i = 4; i < 12; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+8);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = 0;
|
||||
s[5][3] = 0;
|
||||
s[5][4] = MP_DIGIT(a, 20);
|
||||
s[5][5] = MP_DIGIT(a, 21);
|
||||
s[5][6] = MP_DIGIT(a, 22);
|
||||
s[5][7] = MP_DIGIT(a, 23);
|
||||
s[5][8] = 0;
|
||||
s[5][9] = 0;
|
||||
s[5][10] = 0;
|
||||
s[5][11] = 0;
|
||||
s[6][0] = MP_DIGIT(a, 20);
|
||||
s[6][1] = 0;
|
||||
s[6][2] = 0;
|
||||
s[6][3] = MP_DIGIT(a, 21);
|
||||
s[6][4] = MP_DIGIT(a, 22);
|
||||
s[6][5] = MP_DIGIT(a, 23);
|
||||
s[6][6] = 0;
|
||||
s[6][7] = 0;
|
||||
s[6][8] = 0;
|
||||
s[6][9] = 0;
|
||||
s[6][10] = 0;
|
||||
s[6][11] = 0;
|
||||
s[7][0] = MP_DIGIT(a, 23);
|
||||
for (i = 1; i < 12; i++) {
|
||||
s[7][i] = MP_DIGIT(a, i+11);
|
||||
}
|
||||
s[8][0] = 0;
|
||||
s[8][1] = MP_DIGIT(a, 20);
|
||||
s[8][2] = MP_DIGIT(a, 21);
|
||||
s[8][3] = MP_DIGIT(a, 22);
|
||||
s[8][4] = MP_DIGIT(a, 23);
|
||||
s[8][5] = 0;
|
||||
s[8][6] = 0;
|
||||
s[8][7] = 0;
|
||||
s[8][8] = 0;
|
||||
s[8][9] = 0;
|
||||
s[8][10] = 0;
|
||||
s[8][11] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = 0;
|
||||
s[9][2] = 0;
|
||||
s[9][3] = MP_DIGIT(a, 23);
|
||||
s[9][4] = MP_DIGIT(a, 23);
|
||||
s[9][5] = 0;
|
||||
s[9][6] = 0;
|
||||
s[9][7] = 0;
|
||||
s[9][8] = 0;
|
||||
s[9][9] = 0;
|
||||
s[9][10] = 0;
|
||||
s[9][11] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#else
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if ((a_bits > 768) || (a_bits <= 736)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[0][i] = MP_DIGIT(a, i);
|
||||
}
|
||||
s[1][0] = 0;
|
||||
s[1][1] = 0;
|
||||
s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[1][3] = MP_DIGIT(a, 11) >> 32;
|
||||
s[1][4] = 0;
|
||||
s[1][5] = 0;
|
||||
for (i = 0; i < 6; i++) {
|
||||
s[2][i] = MP_DIGIT(a, i+6);
|
||||
}
|
||||
s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32);
|
||||
}
|
||||
s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[4][1] = MP_DIGIT(a, 10) << 32;
|
||||
for (i = 2; i < 6; i++) {
|
||||
s[4][i] = MP_DIGIT(a, i+4);
|
||||
}
|
||||
s[5][0] = 0;
|
||||
s[5][1] = 0;
|
||||
s[5][2] = MP_DIGIT(a, 10);
|
||||
s[5][3] = MP_DIGIT(a, 11);
|
||||
s[5][4] = 0;
|
||||
s[5][5] = 0;
|
||||
s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
|
||||
s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
|
||||
s[6][2] = MP_DIGIT(a, 11);
|
||||
s[6][3] = 0;
|
||||
s[6][4] = 0;
|
||||
s[6][5] = 0;
|
||||
s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
|
||||
for (i = 1; i < 6; i++) {
|
||||
s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32);
|
||||
}
|
||||
s[8][0] = MP_DIGIT(a, 10) << 32;
|
||||
s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
|
||||
s[8][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[8][3] = 0;
|
||||
s[8][4] = 0;
|
||||
s[8][5] = 0;
|
||||
s[9][0] = 0;
|
||||
s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
|
||||
s[9][2] = MP_DIGIT(a, 11) >> 32;
|
||||
s[9][3] = 0;
|
||||
s[9][4] = 0;
|
||||
s[9][5] = 0;
|
||||
|
||||
MP_CHECKOK(mp_add(&m[0], &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[1], r));
|
||||
MP_CHECKOK(mp_add(r, &m[2], r));
|
||||
MP_CHECKOK(mp_add(r, &m[3], r));
|
||||
MP_CHECKOK(mp_add(r, &m[4], r));
|
||||
MP_CHECKOK(mp_add(r, &m[5], r));
|
||||
MP_CHECKOK(mp_add(r, &m[6], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[7], r));
|
||||
MP_CHECKOK(mp_sub(r, &m[8], r));
|
||||
MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
#endif
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p384. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p384.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p384.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p384. */
|
||||
mp_err
|
||||
ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp384(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P384) {
|
||||
group->meth->field_mod = &ec_GFp_nistp384_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp384_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp384_sqr;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECP521_DIGITS ECL_CURVE_DIGITS(521)
|
||||
|
||||
/* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses
|
||||
* algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
|
||||
* Elliptic Curve Cryptography. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int a_bits = mpl_significant_bits(a);
|
||||
int i;
|
||||
|
||||
/* m1, m2 are statically-allocated mp_int of exactly the size we need */
|
||||
mp_int m1;
|
||||
|
||||
mp_digit s1[ECP521_DIGITS] = { 0 };
|
||||
|
||||
MP_SIGN(&m1) = MP_ZPOS;
|
||||
MP_ALLOC(&m1) = ECP521_DIGITS;
|
||||
MP_USED(&m1) = ECP521_DIGITS;
|
||||
MP_DIGITS(&m1) = s1;
|
||||
|
||||
if (a_bits < 521) {
|
||||
if (a==r) return MP_OKAY;
|
||||
return mp_copy(a, r);
|
||||
}
|
||||
/* for polynomials larger than twice the field size or polynomials
|
||||
* not using all words, use regular reduction */
|
||||
if (a_bits > (521*2)) {
|
||||
MP_CHECKOK(mp_mod(a, &meth->irr, r));
|
||||
} else {
|
||||
#define FIRST_DIGIT (ECP521_DIGITS-1)
|
||||
for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
|
||||
s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
|
||||
| (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
|
||||
}
|
||||
s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
|
||||
|
||||
if ( a != r ) {
|
||||
MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
|
||||
for (i = 0; i < ECP521_DIGITS; i++) {
|
||||
MP_DIGIT(r,i) = MP_DIGIT(a, i);
|
||||
}
|
||||
}
|
||||
MP_USED(r) = ECP521_DIGITS;
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
|
||||
MP_CHECKOK(s_mp_add(r, &m1));
|
||||
if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
|
||||
MP_CHECKOK(s_mp_add_d(r,1));
|
||||
MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
|
||||
}
|
||||
s_mp_clamp(r);
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the square of polynomial a, reduce modulo p521. Store the
|
||||
* result in r. r could be a. Uses optimized modular reduction for p521.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_sqr(a, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Compute the product of two polynomials a and b, reduce modulo p521.
|
||||
* Store the result in r. r could be a or b; a could be b. Uses
|
||||
* optimized modular reduction for p521. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Divides two field elements. If a is NULL, then returns the inverse of
|
||||
* b. */
|
||||
mp_err
|
||||
ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t;
|
||||
|
||||
/* If a is NULL, then return the inverse of b, otherwise return a/b. */
|
||||
if (a == NULL) {
|
||||
return mp_invmod(b, &meth->irr, r);
|
||||
} else {
|
||||
/* MPI doesn't support divmod, so we implement it using invmod and
|
||||
* mulmod. */
|
||||
MP_CHECKOK(mp_init(&t));
|
||||
MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
|
||||
MP_CHECKOK(mp_mul(a, &t, r));
|
||||
MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
|
||||
CLEANUP:
|
||||
mp_clear(&t);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire in fast field arithmetic and precomputation of base point for
|
||||
* named curves. */
|
||||
mp_err
|
||||
ec_group_set_gfp521(ECGroup *group, ECCurveName name)
|
||||
{
|
||||
if (name == ECCurve_NIST_P521) {
|
||||
group->meth->field_mod = &ec_GFp_nistp521_mod;
|
||||
group->meth->field_mul = &ec_GFp_nistp521_mul;
|
||||
group->meth->field_sqr = &ec_GFp_nistp521_sqr;
|
||||
group->meth->field_div = &ec_GFp_nistp521_div;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py)
|
||||
{
|
||||
|
||||
if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) {
|
||||
return MP_YES;
|
||||
} else {
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py)
|
||||
{
|
||||
mp_zero(px);
|
||||
mp_zero(py);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
|
||||
* Q, and R can all be identical. Uses affine coordinates. Assumes input
|
||||
* is already field-encoded using field_enc, and returns output that is
|
||||
* still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int lambda, temp, tempx, tempy;
|
||||
|
||||
MP_DIGITS(&lambda) = 0;
|
||||
MP_DIGITS(&temp) = 0;
|
||||
MP_DIGITS(&tempx) = 0;
|
||||
MP_DIGITS(&tempy) = 0;
|
||||
MP_CHECKOK(mp_init(&lambda));
|
||||
MP_CHECKOK(mp_init(&temp));
|
||||
MP_CHECKOK(mp_init(&tempx));
|
||||
MP_CHECKOK(mp_init(&tempy));
|
||||
/* if P = inf, then R = Q */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
|
||||
MP_CHECKOK(mp_copy(qx, rx));
|
||||
MP_CHECKOK(mp_copy(qy, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if Q = inf, then R = P */
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* if px != qx, then lambda = (py-qy) / (px-qx) */
|
||||
if (mp_cmp(px, qx) != 0) {
|
||||
MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempy, &tempx, &lambda, group->meth));
|
||||
} else {
|
||||
/* if py != qy or qy = 0, then R = inf */
|
||||
if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* lambda = (3qx^2+a) / (2qy) */
|
||||
MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 3));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempx, &temp, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&tempx, &group->curvea, &tempx, group->meth));
|
||||
MP_CHECKOK(mp_set_int(&temp, 2));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_div(&tempx, &tempy, &lambda, group->meth));
|
||||
}
|
||||
/* rx = lambda^2 - px - qx */
|
||||
MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
|
||||
/* ry = (x1-x2) * lambda - y1 */
|
||||
MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&tempy, &lambda, &tempy, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
|
||||
MP_CHECKOK(mp_copy(&tempx, rx));
|
||||
MP_CHECKOK(mp_copy(&tempy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&lambda);
|
||||
mp_clear(&temp);
|
||||
mp_clear(&tempx);
|
||||
mp_clear(&tempy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be
|
||||
* identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int nqy;
|
||||
|
||||
MP_DIGITS(&nqy) = 0;
|
||||
MP_CHECKOK(mp_init(&nqy));
|
||||
/* nqy = -qy */
|
||||
MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth));
|
||||
res = group->point_add(px, py, qx, &nqy, rx, ry, group);
|
||||
CLEANUP:
|
||||
mp_clear(&nqy);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* affine coordinates. Assumes input is already field-encoded using
|
||||
* field_enc, and returns output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group);
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
|
||||
* R can be identical. Uses affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int k, k3, qx, qy, sx, sy;
|
||||
int b1, b3, i, l;
|
||||
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&k3) = 0;
|
||||
MP_DIGITS(&qx) = 0;
|
||||
MP_DIGITS(&qy) = 0;
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_CHECKOK(mp_init(&k));
|
||||
MP_CHECKOK(mp_init(&k3));
|
||||
MP_CHECKOK(mp_init(&qx));
|
||||
MP_CHECKOK(mp_init(&qy));
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Q = P, k = n */
|
||||
MP_CHECKOK(mp_copy(px, &qx));
|
||||
MP_CHECKOK(mp_copy(py, &qy));
|
||||
MP_CHECKOK(mp_copy(n, &k));
|
||||
/* if n < 0 then Q = -Q, k = -k */
|
||||
if (mp_cmp_z(n) < 0) {
|
||||
MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
|
||||
MP_CHECKOK(mp_neg(&k, &k));
|
||||
}
|
||||
#ifdef ECL_DEBUG /* basic double and add method */
|
||||
l = mpl_significant_bits(&k) - 1;
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
for (i = l - 1; i >= 0; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
/* if k_i = 1, then S = S + Q */
|
||||
if (mpl_get_bit(&k, i) != 0) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#else /* double and add/subtract method from
|
||||
* standard */
|
||||
/* k3 = 3 * k */
|
||||
MP_CHECKOK(mp_set_int(&k3, 3));
|
||||
MP_CHECKOK(mp_mul(&k, &k3, &k3));
|
||||
/* S = Q */
|
||||
MP_CHECKOK(mp_copy(&qx, &sx));
|
||||
MP_CHECKOK(mp_copy(&qy, &sy));
|
||||
/* l = index of high order bit in binary representation of 3*k */
|
||||
l = mpl_significant_bits(&k3) - 1;
|
||||
/* for i = l-1 downto 1 */
|
||||
for (i = l - 1; i >= 1; i--) {
|
||||
/* S = 2S */
|
||||
MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
|
||||
b3 = MP_GET_BIT(&k3, i);
|
||||
b1 = MP_GET_BIT(&k, i);
|
||||
/* if k3_i = 1 and k_i = 0, then S = S + Q */
|
||||
if ((b3 == 1) && (b1 == 0)) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
/* if k3_i = 0 and k_i = 1, then S = S - Q */
|
||||
} else if ((b3 == 0) && (b1 == 1)) {
|
||||
MP_CHECKOK(group->
|
||||
point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* output S */
|
||||
MP_CHECKOK(mp_copy(&sx, rx));
|
||||
MP_CHECKOK(mp_copy(&sy, ry));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&k);
|
||||
mp_clear(&k3);
|
||||
mp_clear(&qx);
|
||||
mp_clear(&qy);
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Validates a point on a GFp curve. */
|
||||
mp_err
|
||||
ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_NO;
|
||||
mp_int accl, accr, tmp, pxt, pyt;
|
||||
|
||||
MP_DIGITS(&accl) = 0;
|
||||
MP_DIGITS(&accr) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&pxt) = 0;
|
||||
MP_DIGITS(&pyt) = 0;
|
||||
MP_CHECKOK(mp_init(&accl));
|
||||
MP_CHECKOK(mp_init(&accr));
|
||||
MP_CHECKOK(mp_init(&tmp));
|
||||
MP_CHECKOK(mp_init(&pxt));
|
||||
MP_CHECKOK(mp_init(&pyt));
|
||||
|
||||
/* 1: Verify that publicValue is not the point at infinity */
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 2: Verify that the coordinates of publicValue are elements
|
||||
* of the field.
|
||||
*/
|
||||
if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
|
||||
(MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 3: Verify that publicValue is on the curve. */
|
||||
if (group->meth->field_enc) {
|
||||
group->meth->field_enc(px, &pxt, group->meth);
|
||||
group->meth->field_enc(py, &pyt, group->meth);
|
||||
} else {
|
||||
mp_copy(px, &pxt);
|
||||
mp_copy(py, &pyt);
|
||||
}
|
||||
/* left-hand side: y^2 */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
|
||||
/* right-hand side: x^3 + a*x + b */
|
||||
MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
|
||||
MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
|
||||
/* check LHS - RHS == 0 */
|
||||
MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
|
||||
if (mp_cmp_z(&accr) != 0) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* 4: Verify that the order of the curve times the publicValue
|
||||
* is the point at infinity.
|
||||
*/
|
||||
MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
|
||||
if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
res = MP_YES;
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&accl);
|
||||
mp_clear(&accr);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&pxt);
|
||||
mp_clear(&pyt);
|
||||
return res;
|
||||
}
|
||||
@@ -1,568 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves
|
||||
* using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void
|
||||
ecfp_tidyShort(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t, group->alpha, group);
|
||||
}
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void
|
||||
ecfp_tidyUpper(double *t, const EC_group_fp * group)
|
||||
{
|
||||
group->ecfp_tidy(t + group->numDoubles,
|
||||
group->alpha + group->numDoubles, group);
|
||||
}
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. Alternative C version
|
||||
* for portability. */
|
||||
void
|
||||
ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
q = t[i] + alpha[i + 1];
|
||||
q -= alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* If we don't assume that truncation rounding is used, then q
|
||||
* might be 2^n bigger than expected (if it rounds up), then t[0]
|
||||
* could be negative and t[1] 2^n larger than expected. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void
|
||||
ecfp_positiveTidy(double *t, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
int i;
|
||||
|
||||
/* Do carrying */
|
||||
for (i = 0; i < group->numDoubles - 1; i++) {
|
||||
/* Subtract beta to force rounding down */
|
||||
q = t[i] - ecfp_beta[i + 1];
|
||||
q += group->alpha[i + 1];
|
||||
q -= group->alpha[i + 1];
|
||||
t[i] -= q;
|
||||
t[i + 1] += q;
|
||||
|
||||
/* Due to subtracting ecfp_beta, we should have each term a
|
||||
* non-negative int */
|
||||
ECFP_ASSERT(t[i] / ecfp_exp[i] ==
|
||||
(unsigned long long) (t[i] / ecfp_exp[i]));
|
||||
ECFP_ASSERT(t[i] >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup)
|
||||
{
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
unsigned short i16[(group->primeBitSize + 15) / 16];
|
||||
double q = 1;
|
||||
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
/* TEST uint32_t z = 0; */
|
||||
unsigned int z = 0;
|
||||
#else
|
||||
uint64_t z = 0;
|
||||
#endif
|
||||
int zBits = 0;
|
||||
int copiedBits = 0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
mp_digit *out;
|
||||
|
||||
/* Result should always be >= 0, so set sign accordingly */
|
||||
MP_SIGN(mpout) = MP_ZPOS;
|
||||
|
||||
/* Tidy up so we're just dealing with positive numbers */
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* We might need to do this reduction step more than once if the
|
||||
* reduction adds smaller terms which carry-over to cause another
|
||||
* reduction. However, this should happen very rarely, if ever,
|
||||
* depending on the elliptic curve. */
|
||||
do {
|
||||
/* Init loop data */
|
||||
z = 0;
|
||||
zBits = 0;
|
||||
q = 1;
|
||||
i = 0;
|
||||
j = 0;
|
||||
copiedBits = 0;
|
||||
|
||||
/* Might have to do a bit more reduction */
|
||||
group->ecfp_singleReduce(d, group);
|
||||
|
||||
/* Grow the size of the mpint if it's too small */
|
||||
s_mp_grow(mpout, group->numInts);
|
||||
MP_USED(mpout) = group->numInts;
|
||||
out = MP_DIGITS(mpout);
|
||||
|
||||
/* Convert double to 16 bit integers */
|
||||
while (copiedBits < group->primeBitSize) {
|
||||
if (zBits < 16) {
|
||||
z += d[i] * q;
|
||||
i++;
|
||||
ECFP_ASSERT(i < (group->primeBitSize + 15) / 16);
|
||||
zBits += group->doubleBitSize;
|
||||
}
|
||||
i16[j] = z;
|
||||
j++;
|
||||
z >>= 16;
|
||||
zBits -= 16;
|
||||
q *= ecfp_twom16;
|
||||
copiedBits += 16;
|
||||
}
|
||||
} while (z != 0);
|
||||
|
||||
/* Convert 16 bit integers to mp_digit */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) {
|
||||
*out = 0;
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#else /* 64 bit */
|
||||
for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) {
|
||||
*out = 0;
|
||||
if (i + 3 < (group->primeBitSize + 15) / 16) {
|
||||
*out = i16[i + 3];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 2 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 2];
|
||||
*out <<= 16;
|
||||
}
|
||||
if (i + 1 < (group->primeBitSize + 15) / 16) {
|
||||
*out += i16[i + 1];
|
||||
*out <<= 16;
|
||||
}
|
||||
*out++ += i16[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Perform final reduction. mpout should already be the same number
|
||||
* of bits as p, but might not be less than p. Make it so. Since
|
||||
* mpout has the same number of bits as p, and 2p has a larger bit
|
||||
* size, then mpout < 2p, so a single subtraction of p will suffice. */
|
||||
if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) {
|
||||
mp_sub(mpout, &ecgroup->meth->irr, mpout);
|
||||
}
|
||||
|
||||
/* Shrink the size of the mp_int to the actual used size (required for
|
||||
* mp_cmp_z == 0) */
|
||||
out = MP_DIGITS(mpout);
|
||||
for (i = group->numInts - 1; i > 0; i--) {
|
||||
if (out[i] != 0)
|
||||
break;
|
||||
}
|
||||
MP_USED(mpout) = i + 1;
|
||||
|
||||
/* Should be between 0 and p-1 */
|
||||
ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0);
|
||||
ECFP_ASSERT(mp_cmp_z(mpout) >= 0);
|
||||
}
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
int size;
|
||||
double shift = 1;
|
||||
mp_digit *in;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* if debug mode, convert result back using ecfp_fp2i into cmp, then
|
||||
* compare to x. */
|
||||
mp_int cmp;
|
||||
|
||||
MP_DIGITS(&cmp) = NULL;
|
||||
mp_init(&cmp);
|
||||
#endif
|
||||
|
||||
ECFP_ASSERT(group != NULL);
|
||||
|
||||
/* init output to 0 (since we skip over some terms) */
|
||||
for (i = 0; i < group->numDoubles; i++)
|
||||
out[i] = 0;
|
||||
i = 0;
|
||||
|
||||
size = MP_USED(x);
|
||||
in = MP_DIGITS(x);
|
||||
|
||||
/* Copy from int into doubles */
|
||||
#ifdef ECL_THIRTY_TWO_BIT
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 32 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 32 * j);
|
||||
out[i] = in[j];
|
||||
out[i] *= shift;
|
||||
shift *= ecfp_two32;
|
||||
j++;
|
||||
}
|
||||
#else
|
||||
while (j < size) {
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(group->doubleBitSize * i <= 64 * j);
|
||||
out[i] = (in[j] & 0x00000000FFFFFFFF) * shift;
|
||||
|
||||
while (group->doubleBitSize * (i + 1) <= 64 * j + 32) {
|
||||
i++;
|
||||
}
|
||||
ECFP_ASSERT(24 * i <= 64 * j + 32);
|
||||
out[i] = (in[j] & 0xFFFFFFFF00000000) * shift;
|
||||
|
||||
shift *= ecfp_two64;
|
||||
j++;
|
||||
}
|
||||
#endif
|
||||
/* Realign bits to match double boundaries */
|
||||
ecfp_tidyShort(out, group);
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
/* Convert result back to mp_int, compare to original */
|
||||
ecfp_fp2i(&cmp, out, ecgroup);
|
||||
ECFP_ASSERT(mp_cmp(&cmp, x) == 0);
|
||||
mp_clear(&cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses Jacobian coordinates. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
ecfp_jac_pt precomp[16], r;
|
||||
ecfp_aff_pt p;
|
||||
EC_group_fp *group;
|
||||
|
||||
mp_int rz;
|
||||
int i, ni, d;
|
||||
|
||||
ARGCHK(ecgroup != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
group = (EC_group_fp *) ecgroup->extra1;
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
|
||||
/* init p, da */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
|
||||
|
||||
/* Do precomputation */
|
||||
group->precompute_jac(precomp, &p, group);
|
||||
|
||||
/* Do main body of calculations */
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
|
||||
/* R = 2^4 * R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* R = R + (ni * P) */
|
||||
group->pt_add_jac(&r, &precomp[ni], &r, group);
|
||||
}
|
||||
|
||||
/* Convert back to integer */
|
||||
ecfp_fp2i(rx, r.x, ecgroup);
|
||||
ecfp_fp2i(ry, r.y, ecgroup);
|
||||
ecfp_fp2i(&rz, r.z, ecgroup);
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res;
|
||||
mp_int sx, sy, sz;
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jac_pt r;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
|
||||
int i, l;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Init r to point at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* double and add method */
|
||||
l = mpl_significant_bits(n) - 1;
|
||||
|
||||
for (i = l; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jac(&r, &r, group);
|
||||
|
||||
/* if n_i = 1, then R = R + Q */
|
||||
if (MP_GET_BIT(n, i) != 0) {
|
||||
group->pt_add_jac_aff(&r, &p, &r, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point
|
||||
* multiplication from Brown, Hankerson, Lopez, Menezes. Software
|
||||
* Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int sx, sy, sz;
|
||||
EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
|
||||
ecfp_chud_pt precomp[16];
|
||||
|
||||
ecfp_aff_pt p;
|
||||
ecfp_jm_pt r;
|
||||
|
||||
signed char naf[group->orderBitSize + 1];
|
||||
int i;
|
||||
|
||||
MP_DIGITS(&sx) = 0;
|
||||
MP_DIGITS(&sy) = 0;
|
||||
MP_DIGITS(&sz) = 0;
|
||||
MP_CHECKOK(mp_init(&sx));
|
||||
MP_CHECKOK(mp_init(&sy));
|
||||
MP_CHECKOK(mp_init(&sz));
|
||||
|
||||
/* if n = 0 then r = inf */
|
||||
if (mp_cmp_z(n) == 0) {
|
||||
mp_zero(rx);
|
||||
mp_zero(ry);
|
||||
res = MP_OKAY;
|
||||
goto CLEANUP;
|
||||
/* if n < 0 then out of range error */
|
||||
} else if (mp_cmp_z(n) < 0) {
|
||||
res = MP_RANGE;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Convert from integer to floating point */
|
||||
ecfp_i2fp(p.x, px, ecgroup);
|
||||
ecfp_i2fp(p.y, py, ecgroup);
|
||||
ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);
|
||||
|
||||
/* Perform precomputation */
|
||||
group->precompute_chud(precomp, &p, group);
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, group->orderBitSize, n, 5);
|
||||
|
||||
/* Init R = pt at infinity */
|
||||
for (i = 0; i < group->numDoubles; i++) {
|
||||
r.z[i] = 0;
|
||||
}
|
||||
|
||||
/* wNAF method */
|
||||
for (i = group->orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
group->pt_dbl_jm(&r, &r, group);
|
||||
|
||||
if (naf[i] != 0) {
|
||||
group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r,
|
||||
group);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from floating point to integer */
|
||||
ecfp_fp2i(&sx, r.x, ecgroup);
|
||||
ecfp_fp2i(&sy, r.y, ecgroup);
|
||||
ecfp_fp2i(&sz, r.z, ecgroup);
|
||||
|
||||
/* convert result R to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&sx);
|
||||
mp_clear(&sy);
|
||||
mp_clear(&sz);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void
|
||||
ec_GFp_extra_free_fp(ECGroup *group)
|
||||
{
|
||||
if (group->extra1 != NULL) {
|
||||
free(group->extra1);
|
||||
group->extra1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int
|
||||
ec_set_fp_precision(EC_group_fp * group)
|
||||
{
|
||||
double a = 9007199254740992.0; /* 2^53 */
|
||||
double b = a + 1;
|
||||
|
||||
if (a == b) {
|
||||
group->fpPrecision = 53;
|
||||
group->alpha = ecfp_alpha_53;
|
||||
return 53;
|
||||
}
|
||||
group->fpPrecision = 64;
|
||||
group->alpha = ecfp_alpha_64;
|
||||
return 64;
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __ecp_fp_h_
|
||||
#define __ecp_fp_h_
|
||||
|
||||
#include "mpi.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "mpi-priv.h"
|
||||
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Largest number of doubles to store one reduced number in floating
|
||||
* point. Used for memory allocation on the stack. */
|
||||
#define ECFP_MAXDOUBLES 10
|
||||
|
||||
/* For debugging purposes */
|
||||
#ifndef ECL_DEBUG
|
||||
#define ECFP_ASSERT(x)
|
||||
#else
|
||||
#define ECFP_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
/* ECFP_Ti = 2^(i*24) Define as preprocessor constants so we can use in
|
||||
* multiple static constants */
|
||||
#define ECFP_T0 1.0
|
||||
#define ECFP_T1 16777216.0
|
||||
#define ECFP_T2 281474976710656.0
|
||||
#define ECFP_T3 4722366482869645213696.0
|
||||
#define ECFP_T4 79228162514264337593543950336.0
|
||||
#define ECFP_T5 1329227995784915872903807060280344576.0
|
||||
#define ECFP_T6 22300745198530623141535718272648361505980416.0
|
||||
#define ECFP_T7 374144419156711147060143317175368453031918731001856.0
|
||||
#define ECFP_T8 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_T9 105312291668557186697918027683670432318895095400549111254310977536.0
|
||||
#define ECFP_T10 1766847064778384329583297500742918515827483896875618958121606201292619776.0
|
||||
#define ECFP_T11 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0
|
||||
#define ECFP_T12 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056.0
|
||||
#define ECFP_T13 8343699359066055009355553539724812947666814540455674882605631280555545803830627148527195652096.0
|
||||
#define ECFP_T14 139984046386112763159840142535527767382602843577165595931249318810236991948760059086304843329475444736.0
|
||||
#define ECFP_T15 2348542582773833227889480596789337027375682548908319870707290971532209025114608443463698998384768703031934976.0
|
||||
#define ECFP_T16 39402006196394479212279040100143613805079739270465446667948293404245\
|
||||
721771497210611414266254884915640806627990306816.0
|
||||
#define ECFP_T17 66105596879024859895191530803277103982840468296428121928464879527440\
|
||||
5791236311345825189210439715284847591212025023358304256.0
|
||||
#define ECFP_T18 11090678776483259438313656736572334813745748301503266300681918322458\
|
||||
485231222502492159897624416558312389564843845614287315896631296.0
|
||||
#define ECFP_T19 18607071341967536398062689481932916079453218833595342343206149099024\
|
||||
36577570298683715049089827234727835552055312041415509848580169253519\
|
||||
36.0
|
||||
|
||||
#define ECFP_TWO160 1461501637330902918203684832716283019655932542976.0
|
||||
#define ECFP_TWO192 6277101735386680763835789423207666416102355444464034512896.0
|
||||
#define ECFP_TWO224 26959946667150639794667015087019630673637144422540572481103610249216.0
|
||||
|
||||
/* Multiplicative constants */
|
||||
static const double ecfp_two32 = 4294967296.0;
|
||||
static const double ecfp_two64 = 18446744073709551616.0;
|
||||
static const double ecfp_twom16 = .0000152587890625;
|
||||
static const double ecfp_twom128 =
|
||||
.00000000000000000000000000000000000000293873587705571876992184134305561419454666389193021880377187926569604314863681793212890625;
|
||||
static const double ecfp_twom129 =
|
||||
.000000000000000000000000000000000000001469367938527859384960920671527807097273331945965109401885939632848021574318408966064453125;
|
||||
static const double ecfp_twom160 =
|
||||
.0000000000000000000000000000000000000000000000006842277657836020854119773355907793609766904013068924666782559979930620520927053718196475529111921787261962890625;
|
||||
static const double ecfp_twom192 =
|
||||
.000000000000000000000000000000000000000000000000000000000159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625;
|
||||
static const double ecfp_twom224 =
|
||||
.00000000000000000000000000000000000000000000000000000000000000000003709206150687421385731735261547639513367564778757791002453039058917581340095629358997312082723208437536338919136001159027049567384892725385725498199462890625;
|
||||
|
||||
/* ecfp_exp[i] = 2^(i*ECFP_DSIZE) */
|
||||
static const double ecfp_exp[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_T0, ECFP_T1, ECFP_T2, ECFP_T3, ECFP_T4, ECFP_T5,
|
||||
ECFP_T6, ECFP_T7, ECFP_T8, ECFP_T9, ECFP_T10, ECFP_T11,
|
||||
ECFP_T12, ECFP_T13, ECFP_T14, ECFP_T15, ECFP_T16, ECFP_T17, ECFP_T18,
|
||||
ECFP_T19
|
||||
};
|
||||
|
||||
/* 1.1 * 2^52 Uses 2^52 to truncate, the .1 is an extra 2^51 to protect
|
||||
* the 2^52 bit, so that adding alphas to a negative number won't borrow
|
||||
* and empty the important 2^52 bit */
|
||||
#define ECFP_ALPHABASE_53 6755399441055744.0
|
||||
/* Special case: On some platforms, notably x86 Linux, there is an
|
||||
* extended-precision floating point representation with 64-bits of
|
||||
* precision in the mantissa. These extra bits of precision require a
|
||||
* larger value of alpha to truncate, i.e. 1.1 * 2^63. */
|
||||
#define ECFP_ALPHABASE_64 13835058055282163712.0
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(52 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_53[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_53 * ECFP_T0,
|
||||
ECFP_ALPHABASE_53 * ECFP_T1,
|
||||
ECFP_ALPHABASE_53 * ECFP_T2,
|
||||
ECFP_ALPHABASE_53 * ECFP_T3,
|
||||
ECFP_ALPHABASE_53 * ECFP_T4,
|
||||
ECFP_ALPHABASE_53 * ECFP_T5,
|
||||
ECFP_ALPHABASE_53 * ECFP_T6,
|
||||
ECFP_ALPHABASE_53 * ECFP_T7,
|
||||
ECFP_ALPHABASE_53 * ECFP_T8,
|
||||
ECFP_ALPHABASE_53 * ECFP_T9,
|
||||
ECFP_ALPHABASE_53 * ECFP_T10,
|
||||
ECFP_ALPHABASE_53 * ECFP_T11,
|
||||
ECFP_ALPHABASE_53 * ECFP_T12,
|
||||
ECFP_ALPHABASE_53 * ECFP_T13,
|
||||
ECFP_ALPHABASE_53 * ECFP_T14,
|
||||
ECFP_ALPHABASE_53 * ECFP_T15,
|
||||
ECFP_ALPHABASE_53 * ECFP_T16,
|
||||
ECFP_ALPHABASE_53 * ECFP_T17,
|
||||
ECFP_ALPHABASE_53 * ECFP_T18,
|
||||
ECFP_ALPHABASE_53 * ECFP_T19
|
||||
};
|
||||
|
||||
/*
|
||||
* ecfp_alpha[i] = 1.5 * 2^(63 + i*ECFP_DSIZE) we add and subtract alpha
|
||||
* to truncate floating point numbers to a certain number of bits for
|
||||
* tidying */
|
||||
static const double ecfp_alpha_64[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_ALPHABASE_64 * ECFP_T0,
|
||||
ECFP_ALPHABASE_64 * ECFP_T1,
|
||||
ECFP_ALPHABASE_64 * ECFP_T2,
|
||||
ECFP_ALPHABASE_64 * ECFP_T3,
|
||||
ECFP_ALPHABASE_64 * ECFP_T4,
|
||||
ECFP_ALPHABASE_64 * ECFP_T5,
|
||||
ECFP_ALPHABASE_64 * ECFP_T6,
|
||||
ECFP_ALPHABASE_64 * ECFP_T7,
|
||||
ECFP_ALPHABASE_64 * ECFP_T8,
|
||||
ECFP_ALPHABASE_64 * ECFP_T9,
|
||||
ECFP_ALPHABASE_64 * ECFP_T10,
|
||||
ECFP_ALPHABASE_64 * ECFP_T11,
|
||||
ECFP_ALPHABASE_64 * ECFP_T12,
|
||||
ECFP_ALPHABASE_64 * ECFP_T13,
|
||||
ECFP_ALPHABASE_64 * ECFP_T14,
|
||||
ECFP_ALPHABASE_64 * ECFP_T15,
|
||||
ECFP_ALPHABASE_64 * ECFP_T16,
|
||||
ECFP_ALPHABASE_64 * ECFP_T17,
|
||||
ECFP_ALPHABASE_64 * ECFP_T18,
|
||||
ECFP_ALPHABASE_64 * ECFP_T19
|
||||
};
|
||||
|
||||
/* 0.011111111111111111111111 (binary) = 0.5 - 2^25 (24 ones) */
|
||||
#define ECFP_BETABASE 0.4999999701976776123046875
|
||||
|
||||
/*
|
||||
* We subtract beta prior to using alpha to simulate rounding down. We
|
||||
* make this close to 0.5 to round almost everything down, but exactly 0.5
|
||||
* would cause some incorrect rounding. */
|
||||
static const double ecfp_beta[2 * ECFP_MAXDOUBLES] = {
|
||||
ECFP_BETABASE * ECFP_T0,
|
||||
ECFP_BETABASE * ECFP_T1,
|
||||
ECFP_BETABASE * ECFP_T2,
|
||||
ECFP_BETABASE * ECFP_T3,
|
||||
ECFP_BETABASE * ECFP_T4,
|
||||
ECFP_BETABASE * ECFP_T5,
|
||||
ECFP_BETABASE * ECFP_T6,
|
||||
ECFP_BETABASE * ECFP_T7,
|
||||
ECFP_BETABASE * ECFP_T8,
|
||||
ECFP_BETABASE * ECFP_T9,
|
||||
ECFP_BETABASE * ECFP_T10,
|
||||
ECFP_BETABASE * ECFP_T11,
|
||||
ECFP_BETABASE * ECFP_T12,
|
||||
ECFP_BETABASE * ECFP_T13,
|
||||
ECFP_BETABASE * ECFP_T14,
|
||||
ECFP_BETABASE * ECFP_T15,
|
||||
ECFP_BETABASE * ECFP_T16,
|
||||
ECFP_BETABASE * ECFP_T17,
|
||||
ECFP_BETABASE * ECFP_T18,
|
||||
ECFP_BETABASE * ECFP_T19
|
||||
};
|
||||
|
||||
static const double ecfp_beta_160 = ECFP_BETABASE * ECFP_TWO160;
|
||||
static const double ecfp_beta_192 = ECFP_BETABASE * ECFP_TWO192;
|
||||
static const double ecfp_beta_224 = ECFP_BETABASE * ECFP_TWO224;
|
||||
|
||||
/* Affine EC Point. This is the basic representation (x, y) of an elliptic
|
||||
* curve point. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
} ecfp_aff_pt;
|
||||
|
||||
/* Jacobian EC Point. This coordinate system uses X = x/z^2, Y = y/z^3,
|
||||
* which enables calculations with fewer inversions than affine
|
||||
* coordinates. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
} ecfp_jac_pt;
|
||||
|
||||
/* Chudnovsky Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps z^2, z^3 for faster additions. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double z2[ECFP_MAXDOUBLES];
|
||||
double z3[ECFP_MAXDOUBLES];
|
||||
} ecfp_chud_pt;
|
||||
|
||||
/* Modified Jacobian EC Point. This coordinate system is the same as
|
||||
* Jacobian, except it keeps a*z^4 for faster doublings. */
|
||||
typedef struct {
|
||||
double x[ECFP_MAXDOUBLES];
|
||||
double y[ECFP_MAXDOUBLES];
|
||||
double z[ECFP_MAXDOUBLES];
|
||||
double az4[ECFP_MAXDOUBLES];
|
||||
} ecfp_jm_pt;
|
||||
|
||||
struct EC_group_fp_str;
|
||||
|
||||
typedef struct EC_group_fp_str EC_group_fp;
|
||||
struct EC_group_fp_str {
|
||||
int fpPrecision; /* Set to number of bits in mantissa, 53
|
||||
* or 64 */
|
||||
int numDoubles;
|
||||
int primeBitSize;
|
||||
int orderBitSize;
|
||||
int doubleBitSize;
|
||||
int numInts;
|
||||
int aIsM3; /* True if curvea == -3 (mod p), then we
|
||||
* can optimize doubling */
|
||||
double curvea[ECFP_MAXDOUBLES];
|
||||
/* Used to truncate a double to the number of bits in the curve */
|
||||
double bitSize_alpha;
|
||||
/* Pointer to either ecfp_alpha_53 or ecfp_alpha_64 */
|
||||
const double *alpha;
|
||||
|
||||
void (*ecfp_singleReduce) (double *r, const EC_group_fp * group);
|
||||
void (*ecfp_reduce) (double *r, double *x, const EC_group_fp * group);
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of
|
||||
* the doubles is reduced to the regular precision ECFP_DSIZE. This
|
||||
* might result in some float digits being negative. */
|
||||
void (*ecfp_tidy) (double *t, const double *alpha,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine
|
||||
* -> Jacobian. Input and output should be multi-precision floating
|
||||
* point integers. */
|
||||
void (*pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using Jacobian coordinate system. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void (*pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void (*pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group);
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should
|
||||
* be multi-precision floating point integers. */
|
||||
void (*pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group);
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates.
|
||||
* Input and output should be multi-precision floating point integers.
|
||||
*/
|
||||
void (*pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian
|
||||
* points. Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for
|
||||
* -15P, -13P, -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P,
|
||||
* 13P, 15P */
|
||||
void (*precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Chudnovsky Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void (*precompute_jac) (ecfp_jac_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group);
|
||||
|
||||
};
|
||||
|
||||
/* Computes r = x*y.
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void ecfp_multiply(double *r, const double *x, const double *y);
|
||||
|
||||
/* Performs a "tidy" operation, which performs carrying, moving excess
|
||||
* bits from one double to the next double, so that the precision of the
|
||||
* doubles is reduced to the regular precision group->doubleBitSize. This
|
||||
* might result in some float digits being negative. */
|
||||
void ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on only the upper float digits of a multi-precision
|
||||
* floating point integer, i.e. the digits beyond the regular length which
|
||||
* are removed in the reduction step. */
|
||||
void ecfp_tidyUpper(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs tidying on a short multi-precision floating point integer (the
|
||||
* lower group->numDoubles floats). */
|
||||
void ecfp_tidyShort(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Performs a more mathematically precise "tidying" so that each term is
|
||||
* positive. This is slower than the regular tidying, and is used for
|
||||
* conversion from floating point to integer. */
|
||||
void ecfp_positiveTidy(double *t, const EC_group_fp * group);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Uses 4-bit window
|
||||
* method. */
|
||||
mp_err
|
||||
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. The
|
||||
* parameters a, b and p are the elliptic curve coefficients and the prime
|
||||
* that determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates (Jacobian
|
||||
* coordinates for doubles and affine coordinates for additions; based on
|
||||
* recommendation from Brown et al.). Uses window NAF method (algorithm
|
||||
* 11) for scalar-point multiplication from Brown, Hankerson, Lopez,
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *ecgroup);
|
||||
|
||||
/* Uses mixed Jacobian-affine coordinates to perform a point
|
||||
* multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine
|
||||
* coordinates (Jacobian coordinates for doubles and affine coordinates
|
||||
* for additions; based on recommendation from Brown et al.). Not very
|
||||
* time efficient but quite space efficient, no precomputation needed.
|
||||
* group contains the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Performs calculations in floating point number format, since
|
||||
* this is faster than the integer operations on the ULTRASPARC III.
|
||||
* Uses left-to-right binary method (double & add) (algorithm 9) for
|
||||
* scalar-point multiplication from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *ecgroup);
|
||||
|
||||
/* Cleans up extra memory allocated in ECGroup for this implementation. */
|
||||
void ec_GFp_extra_free_fp(ECGroup *group);
|
||||
|
||||
/* Converts from a floating point representation into an mp_int. Expects
|
||||
* that d is already reduced. */
|
||||
void
|
||||
ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup);
|
||||
|
||||
/* Converts from an mpint into a floating point representation. */
|
||||
void
|
||||
ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup);
|
||||
|
||||
/* Tests what precision floating point arithmetic is set to. This should
|
||||
* be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa
|
||||
* (extended precision on x86) and sets it into the EC_group_fp. Returns
|
||||
* either 53 or 64 accordingly. */
|
||||
int ec_set_fp_precision(EC_group_fp * group);
|
||||
|
||||
#endif
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 160
|
||||
#define ECFP_NUMDOUBLES 7
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p, but truncates the number
|
||||
* of bits. */
|
||||
void
|
||||
ecfp160_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom160;
|
||||
d[1] += q * ecfp_twom129;
|
||||
ecfp_positiveTidy(d, group);
|
||||
|
||||
/* Assertions for the highest order term */
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] / ecfp_exp[ECFP_NUMDOUBLES - 1] ==
|
||||
(unsigned long long) (d[ECFP_NUMDOUBLES - 1] /
|
||||
ecfp_exp[ECFP_NUMDOUBLES - 1]));
|
||||
ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] >= 0);
|
||||
}
|
||||
|
||||
/* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should not already be reduced, i.e. should have
|
||||
* 2*ECFP_NUMDOUBLES significant terms. x and r can be the same, but then
|
||||
* the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp160_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x7, x8, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 160);
|
||||
ECFP_ASSERT(ECFP_NUMDOUBLES == 7);
|
||||
|
||||
/* Tidy just the upper bits, the lower bits can wait. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
/* Assume that this is already tidied so that we have enough extra
|
||||
* bits */
|
||||
x7 = x[7] + x[13] * ecfp_twom129; /* adds bits 15-39 */
|
||||
|
||||
/* Tidy x7, or we won't have enough bits later to add it in */
|
||||
q = x7 + group->alpha[8];
|
||||
q -= group->alpha[8];
|
||||
x7 -= q; /* holds bits 0-24 */
|
||||
x8 = x[8] + q; /* holds bits 0-25 */
|
||||
|
||||
r[6] = x[6] + x[13] * ecfp_twom160 + x[12] * ecfp_twom129; /* adds
|
||||
* bits
|
||||
* 8-39 */
|
||||
r[5] = x[5] + x[12] * ecfp_twom160 + x[11] * ecfp_twom129;
|
||||
r[4] = x[4] + x[11] * ecfp_twom160 + x[10] * ecfp_twom129;
|
||||
r[3] = x[3] + x[10] * ecfp_twom160 + x[9] * ecfp_twom129;
|
||||
r[2] = x[2] + x[9] * ecfp_twom160 + x8 * ecfp_twom129; /* adds bits
|
||||
* 8-40 */
|
||||
r[1] = x[1] + x8 * ecfp_twom160 + x7 * ecfp_twom129; /* adds bits
|
||||
* 8-39 */
|
||||
r[0] = x[0] + x7 * ecfp_twom160;
|
||||
|
||||
/* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate, which is more costly.) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive result */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_160;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom160;
|
||||
r[1] += q * ecfp_twom129;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_secp160r1_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg = NULL;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 161;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp160_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp160_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp160_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp160_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp160_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp160_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp160_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp160_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp160_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp160_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp160_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO160 * fpg->alpha[0];
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 192
|
||||
#define ECFP_NUMDOUBLES 8
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp192_singleReduce(double *d, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
d[ECFP_NUMDOUBLES - 1] -= q;
|
||||
d[0] += q * ecfp_twom192;
|
||||
d[2] += q * ecfp_twom128;
|
||||
ecfp_positiveTidy(d, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 16, and r at least 8 x and
|
||||
* r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp_reduce_192(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
double x8, x9, x10, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 192);
|
||||
ECFP_ASSERT(group->numDoubles == 8);
|
||||
|
||||
/* Tidy just the upper portion, the lower part can wait */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x8 = x[8] + x[14] * ecfp_twom128; /* adds bits 16-40 */
|
||||
x9 = x[9] + x[15] * ecfp_twom128; /* adds bits 16-40 */
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
|
||||
q = x8 + group->alpha[9];
|
||||
q -= group->alpha[9];
|
||||
x8 -= q;
|
||||
x9 += q;
|
||||
|
||||
q = x9 + group->alpha[10];
|
||||
q -= group->alpha[10];
|
||||
x9 -= q;
|
||||
x10 = x[10] + q;
|
||||
|
||||
r[7] = x[7] + x[15] * ecfp_twom192 + x[13] * ecfp_twom128; /* adds
|
||||
* bits
|
||||
* 0-40 */
|
||||
r[6] = x[6] + x[14] * ecfp_twom192 + x[12] * ecfp_twom128;
|
||||
r[5] = x[5] + x[13] * ecfp_twom192 + x[11] * ecfp_twom128;
|
||||
r[4] = x[4] + x[12] * ecfp_twom192 + x10 * ecfp_twom128;
|
||||
r[3] = x[3] + x[11] * ecfp_twom192 + x9 * ecfp_twom128; /* adds bits
|
||||
* 0-40 */
|
||||
r[2] = x[2] + x10 * ecfp_twom192 + x8 * ecfp_twom128;
|
||||
r[1] = x[1] + x9 * ecfp_twom192; /* adds bits 16-40 */
|
||||
r[0] = x[0] + x8 * ecfp_twom192;
|
||||
|
||||
/*
|
||||
* Tidy up just r[group->numDoubles-2] so that the number of
|
||||
* reductions is accurate plus or minus one. (Rather than tidy all to
|
||||
* make it totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[group->numDoubles-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_192;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] += q * ecfp_twom192;
|
||||
r[2] += q * ecfp_twom128;
|
||||
|
||||
/* Tidy the result */
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp192_fp(ECGroup *group)
|
||||
{
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 192;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp192_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp_reduce_192;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp192_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp192_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp192_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp192_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp192_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp192_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp192_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp192_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp192_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO192 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp_fp.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ECFP_BSIZE 224
|
||||
#define ECFP_NUMDOUBLES 10
|
||||
|
||||
#include "ecp_fpinc.c"
|
||||
|
||||
/* Performs a single step of reduction, just on the uppermost float
|
||||
* (assumes already tidied), and then retidies. Note, this does not
|
||||
* guarantee that the result will be less than p. */
|
||||
void
|
||||
ecfp224_singleReduce(double *r, const EC_group_fp * group)
|
||||
{
|
||||
double q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_positiveTidy(r, group);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs imperfect reduction. This might leave some negative terms,
|
||||
* and one more reduction might be required for the result to be between 0
|
||||
* and p-1. x should be be an array of at least 20, and r at least 10 x
|
||||
* and r can be the same, but then the upper parts of r are not zeroed */
|
||||
void
|
||||
ecfp224_reduce(double *r, double *x, const EC_group_fp * group)
|
||||
{
|
||||
|
||||
double x10, x11, x12, x13, x14, q;
|
||||
|
||||
ECFP_ASSERT(group->doubleBitSize == 24);
|
||||
ECFP_ASSERT(group->primeBitSize == 224);
|
||||
ECFP_ASSERT(group->numDoubles == 10);
|
||||
|
||||
/* Tidy just the upper bits of x. Don't need to tidy the lower ones
|
||||
* yet. */
|
||||
ecfp_tidyUpper(x, group);
|
||||
|
||||
x10 = x[10] + x[16] * ecfp_twom128;
|
||||
x11 = x[11] + x[17] * ecfp_twom128;
|
||||
x12 = x[12] + x[18] * ecfp_twom128;
|
||||
x13 = x[13] + x[19] * ecfp_twom128;
|
||||
|
||||
/* Tidy up, or we won't have enough bits later to add it in */
|
||||
q = x10 + group->alpha[11];
|
||||
q -= group->alpha[11];
|
||||
x10 -= q;
|
||||
x11 = x11 + q;
|
||||
|
||||
q = x11 + group->alpha[12];
|
||||
q -= group->alpha[12];
|
||||
x11 -= q;
|
||||
x12 = x12 + q;
|
||||
|
||||
q = x12 + group->alpha[13];
|
||||
q -= group->alpha[13];
|
||||
x12 -= q;
|
||||
x13 = x13 + q;
|
||||
|
||||
q = x13 + group->alpha[14];
|
||||
q -= group->alpha[14];
|
||||
x13 -= q;
|
||||
x14 = x[14] + q;
|
||||
|
||||
r[9] = x[9] + x[15] * ecfp_twom128 - x[19] * ecfp_twom224;
|
||||
r[8] = x[8] + x14 * ecfp_twom128 - x[18] * ecfp_twom224;
|
||||
r[7] = x[7] + x13 * ecfp_twom128 - x[17] * ecfp_twom224;
|
||||
r[6] = x[6] + x12 * ecfp_twom128 - x[16] * ecfp_twom224;
|
||||
r[5] = x[5] + x11 * ecfp_twom128 - x[15] * ecfp_twom224;
|
||||
r[4] = x[4] + x10 * ecfp_twom128 - x14 * ecfp_twom224;
|
||||
r[3] = x[3] - x13 * ecfp_twom224;
|
||||
r[2] = x[2] - x12 * ecfp_twom224;
|
||||
r[1] = x[1] - x11 * ecfp_twom224;
|
||||
r[0] = x[0] - x10 * ecfp_twom224;
|
||||
|
||||
/*
|
||||
* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions
|
||||
* is accurate plus or minus one. (Rather than tidy all to make it
|
||||
* totally accurate) */
|
||||
q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
q -= group->alpha[ECFP_NUMDOUBLES - 1];
|
||||
r[ECFP_NUMDOUBLES - 2] -= q;
|
||||
r[ECFP_NUMDOUBLES - 1] += q;
|
||||
|
||||
/* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */
|
||||
/* Use ecfp_beta so we get a positive res */
|
||||
q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224;
|
||||
q += group->bitSize_alpha;
|
||||
q -= group->bitSize_alpha;
|
||||
|
||||
r[ECFP_NUMDOUBLES - 1] -= q;
|
||||
r[0] -= q * ecfp_twom224;
|
||||
r[4] += q * ecfp_twom128;
|
||||
|
||||
ecfp_tidyShort(r, group);
|
||||
}
|
||||
|
||||
/* Sets group to use optimized calculations in this file */
|
||||
mp_err
|
||||
ec_group_set_nistp224_fp(ECGroup *group)
|
||||
{
|
||||
|
||||
EC_group_fp *fpg;
|
||||
|
||||
/* Allocate memory for floating point group data */
|
||||
fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp));
|
||||
if (fpg == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
fpg->numDoubles = ECFP_NUMDOUBLES;
|
||||
fpg->primeBitSize = ECFP_BSIZE;
|
||||
fpg->orderBitSize = 224;
|
||||
fpg->doubleBitSize = 24;
|
||||
fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS;
|
||||
fpg->aIsM3 = 1;
|
||||
fpg->ecfp_singleReduce = &ecfp224_singleReduce;
|
||||
fpg->ecfp_reduce = &ecfp224_reduce;
|
||||
fpg->ecfp_tidy = &ecfp_tidy;
|
||||
|
||||
fpg->pt_add_jac_aff = &ecfp224_pt_add_jac_aff;
|
||||
fpg->pt_add_jac = &ecfp224_pt_add_jac;
|
||||
fpg->pt_add_jm_chud = &ecfp224_pt_add_jm_chud;
|
||||
fpg->pt_add_chud = &ecfp224_pt_add_chud;
|
||||
fpg->pt_dbl_jac = &ecfp224_pt_dbl_jac;
|
||||
fpg->pt_dbl_jm = &ecfp224_pt_dbl_jm;
|
||||
fpg->pt_dbl_aff2chud = &ecfp224_pt_dbl_aff2chud;
|
||||
fpg->precompute_chud = &ecfp224_precompute_chud;
|
||||
fpg->precompute_jac = &ecfp224_precompute_jac;
|
||||
|
||||
group->point_mul = &ec_GFp_point_mul_wNAF_fp;
|
||||
group->points_mul = &ec_pts_mul_basic;
|
||||
group->extra1 = fpg;
|
||||
group->extra_free = &ec_GFp_extra_free_fp;
|
||||
|
||||
ec_set_fp_precision(fpg);
|
||||
fpg->bitSize_alpha = ECFP_TWO224 * fpg->alpha[0];
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
@@ -1,855 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves using floating point operations.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* This source file is meant to be included by other source files
|
||||
* (ecp_fp###.c, where ### is one of 160, 192, 224) and should not
|
||||
* constitute an independent compilation unit. It requires the following
|
||||
* preprocessor definitions be made: ECFP_BSIZE - the number of bits in
|
||||
* the field's prime
|
||||
* ECFP_NUMDOUBLES - the number of doubles to store one
|
||||
* multi-precision integer in floating point
|
||||
|
||||
/* Adds a prefix to a given token to give a unique token name. Prefixes
|
||||
* with "ecfp" + ECFP_BSIZE + "_". e.g. if ECFP_BSIZE = 160, then
|
||||
* PREFIX(hello) = ecfp160_hello This optimization allows static function
|
||||
* linking and compiler loop unrolling without code duplication. */
|
||||
#ifndef PREFIX
|
||||
#define PREFIX(b) PREFIX1(ECFP_BSIZE, b)
|
||||
#define PREFIX1(bsize, b) PREFIX2(bsize, b)
|
||||
#define PREFIX2(bsize, b) ecfp ## bsize ## _ ## b
|
||||
#endif
|
||||
|
||||
/* Returns true iff every double in d is 0. (If d == 0 and it is tidied,
|
||||
* this will be true.) */
|
||||
mp_err PREFIX(isZero) (const double *d) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
if (d[i] != 0)
|
||||
return MP_NO;
|
||||
}
|
||||
return MP_YES;
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 0 */
|
||||
void PREFIX(zero) (double *t) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the multi-precision floating point number at t = 1 */
|
||||
void PREFIX(one) (double *t) {
|
||||
int i;
|
||||
|
||||
t[0] = 1;
|
||||
for (i = 1; i < ECFP_NUMDOUBLES; i++) {
|
||||
t[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z) is at infinity. Uses Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jac) (const ecfp_jac_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jac) (ecfp_jac_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y) is at infinity. Uses Affine coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_aff) (const ecfp_aff_pt * p) {
|
||||
if (PREFIX(isZero) (p->x) == MP_YES && PREFIX(isZero) (p->y) == MP_YES)
|
||||
return MP_YES;
|
||||
return MP_NO;
|
||||
}
|
||||
|
||||
/* Sets the affine point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_aff) (ecfp_aff_pt * p) {
|
||||
PREFIX(zero) (p->x);
|
||||
PREFIX(zero) (p->y);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, a*z^4) is at infinity. Uses Modified
|
||||
* Jacobian coordinates. */
|
||||
mp_err PREFIX(pt_is_inf_jm) (const ecfp_jm_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Modified Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_jm) (ecfp_jm_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Checks if point P(x, y, z, z^2, z^3) is at infinity. Uses Chudnovsky
|
||||
* Jacobian coordinates */
|
||||
mp_err PREFIX(pt_is_inf_chud) (const ecfp_chud_pt * p) {
|
||||
return PREFIX(isZero) (p->z);
|
||||
}
|
||||
|
||||
/* Sets the Chudnovsky Jacobian point P to be at infinity. */
|
||||
void PREFIX(set_pt_inf_chud) (ecfp_chud_pt * p) {
|
||||
PREFIX(zero) (p->z);
|
||||
}
|
||||
|
||||
/* Copies a multi-precision floating point number, Setting dest = src */
|
||||
void PREFIX(copy) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets dest = -src */
|
||||
void PREFIX(negLong) (double *dest, const double *src) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
dest[i] = -src[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets r = -p p = (x, y, z, z2, z3) r = (x, -y, z, z2, z3) Uses
|
||||
* Chudnovsky Jacobian coordinates. */
|
||||
/* TODO reverse order */
|
||||
void PREFIX(pt_neg_chud) (const ecfp_chud_pt * p, ecfp_chud_pt * r) {
|
||||
int i;
|
||||
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
r->y[i] = -p->y[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first ECFP_NUMDOUBLES
|
||||
* doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise adds first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(addLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ + *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractShort) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x,
|
||||
* y can point to the same data. Componentwise subtracts first
|
||||
* 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */
|
||||
void PREFIX(subtractLong) (double *r, const double *x, const double *y) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) {
|
||||
*r++ = *x++ - *y++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes r = x*y. Both x and y should be tidied and reduced,
|
||||
* r must be different (point to different memory) than x and y.
|
||||
* Does not tidy or reduce. */
|
||||
void PREFIX(multiply)(double *r, const double *x, const double *y) {
|
||||
int i, j;
|
||||
|
||||
for(j=0;j<ECFP_NUMDOUBLES-1;j++) {
|
||||
r[j] = x[0] * y[j];
|
||||
r[j+(ECFP_NUMDOUBLES-1)] = x[ECFP_NUMDOUBLES-1] * y[j];
|
||||
}
|
||||
r[ECFP_NUMDOUBLES-1] = x[0] * y[ECFP_NUMDOUBLES-1];
|
||||
r[ECFP_NUMDOUBLES-1] += x[ECFP_NUMDOUBLES-1] * y[0];
|
||||
r[2*ECFP_NUMDOUBLES-2] = x[ECFP_NUMDOUBLES-1] * y[ECFP_NUMDOUBLES-1];
|
||||
r[2*ECFP_NUMDOUBLES-1] = 0;
|
||||
|
||||
for(i=1;i<ECFP_NUMDOUBLES-1;i++) {
|
||||
for(j=0;j<ECFP_NUMDOUBLES;j++) {
|
||||
r[i+j] += (x[i] * y[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the square of x and stores the result in r. x should be
|
||||
* tidied & reduced, r will be neither tidied nor reduced.
|
||||
* r should point to different memory than x */
|
||||
void PREFIX(square) (double *r, const double *x) {
|
||||
PREFIX(multiply) (r, x, x);
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Jacobian coordinates. Input and output
|
||||
* should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jac) (dp) == MP_YES) {
|
||||
/* Set r = pt at infinity */
|
||||
PREFIX(set_pt_inf_jac) (dr);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Perform typical point doubling operations */
|
||||
|
||||
/* TODO? is it worthwhile to do optimizations for when pz = 1? */
|
||||
|
||||
if (group->aIsM3) {
|
||||
/* When a = -3, M = 3(px - pz^2)(px + pz^2) */
|
||||
PREFIX(square) (t1, dp->z);
|
||||
group->ecfp_reduce(t1, t1, group); /* 2^23 since the negative
|
||||
* rounding buys another bit */
|
||||
PREFIX(addShort) (t0, dp->x, t1); /* 2*2^23 */
|
||||
PREFIX(subtractShort) (t1, dp->x, t1); /* 2 * 2^23 */
|
||||
PREFIX(multiply) (M, t0, t1); /* 40 * 2^46 */
|
||||
PREFIX(addLong) (t0, M, M); /* 80 * 2^46 */
|
||||
PREFIX(addLong) (M, t0, M); /* 120 * 2^46 < 2^53 */
|
||||
group->ecfp_reduce(M, M, group);
|
||||
} else {
|
||||
/* Generic case */
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, dp->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(square) (M, dp->z);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
PREFIX(square) (t1, M);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (M, t1, group->curvea); /* M = a(pz^4) */
|
||||
PREFIX(addLong) (M, M, t0);
|
||||
group->ecfp_reduce(M, M, group);
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, dp->y, dp->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(dr->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2 */
|
||||
PREFIX(square) (t0, dp->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, dp->x, t0);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
PREFIX(square) (t1, M);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
PREFIX(subtractShort) (t1, t1, S);
|
||||
group->ecfp_reduce(dr->x, t1, group);
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
PREFIX(square) (t1, t0); /* t1 = 4y^4 */
|
||||
PREFIX(subtractShort) (S, S, dr->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
PREFIX(subtractLong) (t0, t0, t1);
|
||||
group->ecfp_reduce(dr->y, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinate system Jacobian + Affine ->
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
/* Temporary storage */
|
||||
double A[2 * ECFP_NUMDOUBLES], B[2 * ECFP_NUMDOUBLES],
|
||||
C[2 * ECFP_NUMDOUBLES], C2[2 * ECFP_NUMDOUBLES],
|
||||
D[2 * ECFP_NUMDOUBLES], C3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p or q */
|
||||
if (PREFIX(pt_is_inf_aff) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
} else if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
/* Since the affine point is not infinity, we can set r->z = 1 */
|
||||
PREFIX(one) (r->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Calculates c = qx * pz^2 - px d = (qy * b - py) rx = d^2 - c^3 + 2
|
||||
* (px * c^2) ry = d * (c-rx) - py*c^3 rz = c * pz */
|
||||
|
||||
/* A = pz^2, B = pz^3 */
|
||||
PREFIX(square) (A, p->z);
|
||||
group->ecfp_reduce(A, A, group);
|
||||
PREFIX(multiply) (B, A, p->z);
|
||||
group->ecfp_reduce(B, B, group);
|
||||
|
||||
/* C = qx * A - px */
|
||||
PREFIX(multiply) (C, q->x, A);
|
||||
PREFIX(subtractShort) (C, C, p->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* D = qy * B - py */
|
||||
PREFIX(multiply) (D, q->y, B);
|
||||
PREFIX(subtractShort) (D, D, p->y);
|
||||
group->ecfp_reduce(D, D, group);
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
PREFIX(square) (C2, C);
|
||||
group->ecfp_reduce(C2, C2, group);
|
||||
PREFIX(multiply) (C3, C2, C);
|
||||
group->ecfp_reduce(C3, C3, group);
|
||||
|
||||
/* rz = A = pz * C */
|
||||
PREFIX(multiply) (A, p->z, C);
|
||||
group->ecfp_reduce(r->z, A, group);
|
||||
|
||||
/* C = px * C^2, untidied, unreduced */
|
||||
PREFIX(multiply) (C, p->x, C2);
|
||||
|
||||
/* A = D^2, untidied, unreduced */
|
||||
PREFIX(square) (A, D);
|
||||
|
||||
/* rx = B = A - C3 - C - C = D^2 - (C^3 + 2 * (px * C^2) */
|
||||
PREFIX(subtractShort) (A, A, C3);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
PREFIX(subtractLong) (A, A, C);
|
||||
group->ecfp_reduce(r->x, A, group);
|
||||
|
||||
/* B = py * C3, untidied, unreduced */
|
||||
PREFIX(multiply) (B, p->y, C3);
|
||||
|
||||
/* C = px * C^2 - rx */
|
||||
PREFIX(subtractShort) (C, C, r->x);
|
||||
group->ecfp_reduce(C, C, group);
|
||||
|
||||
/* ry = A = D * C - py * C^3 */
|
||||
PREFIX(multiply) (A, D, C);
|
||||
PREFIX(subtractLong) (A, A, B);
|
||||
group->ecfp_reduce(r->y, A, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Jacobian coordinate system. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q,
|
||||
ecfp_jac_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_jac) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 , S = py * qz^3 */
|
||||
PREFIX(square) (t0, q->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (U, p->x, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(multiply) (t1, t0, q->z);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->y, t1);
|
||||
group->ecfp_reduce(S, t0, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U , R = (qy * pz^3 - S) */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (H, q->x, t0);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(multiply) (t1, t0, p->z); /* t1 = pz^3 */
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, t1, q->y); /* t0 = qy * pz^3 */
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling in Modified Jacobian coordinates. Input and
|
||||
* output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
/* Temporary storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], T[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
PREFIX(set_pt_inf_jm) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (M, t0, t0);
|
||||
PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */
|
||||
PREFIX(addShort) (t0, t0, p->az4);
|
||||
group->ecfp_reduce(M, t0, group);
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
PREFIX(multiply) (t1, p->y, p->z);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* t0 = 2y^2, U = 8y^4 */
|
||||
PREFIX(square) (t0, p->y);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(addShort) (t0, t0, t0);
|
||||
PREFIX(square) (U, t0);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
PREFIX(addShort) (U, U, U);
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
PREFIX(multiply) (S, p->x, t0);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
PREFIX(addShort) (S, S, S);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (T, M);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
PREFIX(subtractShort) (T, T, S);
|
||||
group->ecfp_reduce(r->x, T, group);
|
||||
|
||||
/* ry = M * (S - rx) - U */
|
||||
PREFIX(subtractShort) (S, S, r->x);
|
||||
PREFIX(multiply) (t0, M, S);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->y, t0, group);
|
||||
|
||||
/* ra*z^4 = 2*U*(apz4) */
|
||||
PREFIX(multiply) (t1, U, p->az4);
|
||||
PREFIX(addLong) (t1, t1, t1);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point doubling using coordinates Affine -> Chudnovsky
|
||||
* Jacobian. Input and output should be multi-precision floating point
|
||||
* integers. */
|
||||
void PREFIX(pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r,
|
||||
const EC_group_fp * group) {
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
M[2 * ECFP_NUMDOUBLES], twoY2[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = O */
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(set_pt_inf_chud) (r);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3(px)^2 + a */
|
||||
PREFIX(square) (t0, p->x);
|
||||
PREFIX(addLong) (t1, t0, t0);
|
||||
PREFIX(addLong) (t1, t1, t0);
|
||||
PREFIX(addShort) (t1, t1, group->curvea);
|
||||
group->ecfp_reduce(M, t1, group);
|
||||
|
||||
/* twoY2 = 2*(py)^2, S = 4(px)(py)^2 */
|
||||
PREFIX(square) (twoY2, p->y);
|
||||
PREFIX(addLong) (twoY2, twoY2, twoY2);
|
||||
group->ecfp_reduce(twoY2, twoY2, group);
|
||||
PREFIX(multiply) (S, p->x, twoY2);
|
||||
PREFIX(addLong) (S, S, S);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
PREFIX(square) (t0, M);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = M(S-rx) - 8y^4 */
|
||||
PREFIX(subtractShort) (t0, S, r->x);
|
||||
PREFIX(multiply) (t1, t0, M);
|
||||
PREFIX(square) (t0, twoY2);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
PREFIX(subtractLong) (t1, t1, t0);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz = 2py */
|
||||
PREFIX(addShort) (r->z, p->y, p->y);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using coordinates: Modified Jacobian +
|
||||
* Chudnovsky Jacobian -> Modified Jacobian. Input and output should be
|
||||
* multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q,
|
||||
ecfp_jm_pt * r, const EC_group_fp * group) {
|
||||
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES], pz2[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q need to convert
|
||||
* from Chudnovsky form to Modified Jacobian form */
|
||||
if (PREFIX(pt_is_inf_jm) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(square) (t0, q->z2);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, group->curvea);
|
||||
group->ecfp_reduce(r->az4, t1, group);
|
||||
goto CLEANUP;
|
||||
}
|
||||
/* Check for point at infinity for q, if so set r = p */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->az4, p->az4);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(square) (t0, p->z);
|
||||
group->ecfp_reduce(pz2, t0, group);
|
||||
PREFIX(multiply) (H, pz2, q->x);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, pz2, p->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (R, t0, q->y);
|
||||
PREFIX(subtractShort) (R, R, S);
|
||||
group->ecfp_reduce(R, R, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t1, q->z, H);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, p->z, t1);
|
||||
group->ecfp_reduce(r->z, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
if (group->aIsM3) { /* a == -3 */
|
||||
/* a(rz^4) = -3 * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
PREFIX(addLong) (t0, t1, t1);
|
||||
PREFIX(addLong) (t0, t0, t1);
|
||||
PREFIX(negLong) (t0, t0);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
} else { /* Generic case */
|
||||
/* a(rz^4) = a * ((rz^2)^2) */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(square) (t1, t0);
|
||||
group->ecfp_reduce(t1, t1, group);
|
||||
PREFIX(multiply) (t0, group->curvea, t1);
|
||||
group->ecfp_reduce(r->az4, t0, group);
|
||||
}
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a point addition using Chudnovsky Jacobian coordinates. Input
|
||||
* and output should be multi-precision floating point integers. */
|
||||
void PREFIX(pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q,
|
||||
ecfp_chud_pt * r, const EC_group_fp * group) {
|
||||
|
||||
/* Temporary Storage */
|
||||
double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES],
|
||||
U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES],
|
||||
S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES],
|
||||
H3[2 * ECFP_NUMDOUBLES];
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (p) == MP_YES) {
|
||||
PREFIX(copy) (r->x, q->x);
|
||||
PREFIX(copy) (r->y, q->y);
|
||||
PREFIX(copy) (r->z, q->z);
|
||||
PREFIX(copy) (r->z2, q->z2);
|
||||
PREFIX(copy) (r->z3, q->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Check for point at infinity for p, if so set r = q */
|
||||
if (PREFIX(pt_is_inf_chud) (q) == MP_YES) {
|
||||
PREFIX(copy) (r->x, p->x);
|
||||
PREFIX(copy) (r->y, p->y);
|
||||
PREFIX(copy) (r->z, p->z);
|
||||
PREFIX(copy) (r->z2, p->z2);
|
||||
PREFIX(copy) (r->z3, p->z3);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* U = px * qz^2 */
|
||||
PREFIX(multiply) (U, p->x, q->z2);
|
||||
group->ecfp_reduce(U, U, group);
|
||||
|
||||
/* H = qx*(pz)^2 - U */
|
||||
PREFIX(multiply) (H, q->x, p->z2);
|
||||
PREFIX(subtractShort) (H, H, U);
|
||||
group->ecfp_reduce(H, H, group);
|
||||
|
||||
/* U = U*H^2, H3 = H^3 */
|
||||
PREFIX(square) (t0, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, U, t0);
|
||||
group->ecfp_reduce(U, t1, group);
|
||||
PREFIX(multiply) (H3, t0, H);
|
||||
group->ecfp_reduce(H3, H3, group);
|
||||
|
||||
/* S = py * qz^3 */
|
||||
PREFIX(multiply) (S, p->y, q->z3);
|
||||
group->ecfp_reduce(S, S, group);
|
||||
|
||||
/* rz = pz * qz * H */
|
||||
PREFIX(multiply) (t0, q->z, H);
|
||||
group->ecfp_reduce(t0, t0, group);
|
||||
PREFIX(multiply) (t1, t0, p->z);
|
||||
group->ecfp_reduce(r->z, t1, group);
|
||||
|
||||
/* R = (qy * z1^3 - s) */
|
||||
PREFIX(multiply) (t0, q->y, p->z3);
|
||||
PREFIX(subtractShort) (t0, t0, S);
|
||||
group->ecfp_reduce(R, t0, group);
|
||||
|
||||
/* rx = R^2 - H^3 - 2 * U */
|
||||
PREFIX(square) (t0, R);
|
||||
PREFIX(subtractShort) (t0, t0, H3);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
PREFIX(subtractShort) (t0, t0, U);
|
||||
group->ecfp_reduce(r->x, t0, group);
|
||||
|
||||
/* ry = R(U - rx) - S*H3 */
|
||||
PREFIX(subtractShort) (t1, U, r->x);
|
||||
PREFIX(multiply) (t0, t1, R);
|
||||
PREFIX(multiply) (t1, S, H3);
|
||||
PREFIX(subtractLong) (t1, t0, t1);
|
||||
group->ecfp_reduce(r->y, t1, group);
|
||||
|
||||
/* rz2 = rz^2 */
|
||||
PREFIX(square) (t0, r->z);
|
||||
group->ecfp_reduce(r->z2, t0, group);
|
||||
|
||||
/* rz3 = rz^3 */
|
||||
PREFIX(multiply) (t0, r->z, r->z2);
|
||||
group->ecfp_reduce(r->z3, t0, group);
|
||||
|
||||
CLEANUP:
|
||||
return;
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Chudnovsky Jacobian points.
|
||||
* Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for -15P, -13P,
|
||||
* -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, 13P, 15P */
|
||||
void PREFIX(precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
|
||||
ecfp_chud_pt p2;
|
||||
|
||||
/* Set out[8] = P */
|
||||
PREFIX(copy) (out[8].x, p->x);
|
||||
PREFIX(copy) (out[8].y, p->y);
|
||||
PREFIX(one) (out[8].z);
|
||||
PREFIX(one) (out[8].z2);
|
||||
PREFIX(one) (out[8].z3);
|
||||
|
||||
/* Set p2 = 2P */
|
||||
PREFIX(pt_dbl_aff2chud) (p, &p2, group);
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
PREFIX(pt_add_chud) (&out[8], &p2, &out[9], group);
|
||||
PREFIX(pt_add_chud) (&out[9], &p2, &out[10], group);
|
||||
PREFIX(pt_add_chud) (&out[10], &p2, &out[11], group);
|
||||
PREFIX(pt_add_chud) (&out[11], &p2, &out[12], group);
|
||||
PREFIX(pt_add_chud) (&out[12], &p2, &out[13], group);
|
||||
PREFIX(pt_add_chud) (&out[13], &p2, &out[14], group);
|
||||
PREFIX(pt_add_chud) (&out[14], &p2, &out[15], group);
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
PREFIX(pt_neg_chud) (&out[8], &out[7]);
|
||||
PREFIX(pt_neg_chud) (&out[9], &out[6]);
|
||||
PREFIX(pt_neg_chud) (&out[10], &out[5]);
|
||||
PREFIX(pt_neg_chud) (&out[11], &out[4]);
|
||||
PREFIX(pt_neg_chud) (&out[12], &out[3]);
|
||||
PREFIX(pt_neg_chud) (&out[13], &out[2]);
|
||||
PREFIX(pt_neg_chud) (&out[14], &out[1]);
|
||||
PREFIX(pt_neg_chud) (&out[15], &out[0]);
|
||||
}
|
||||
|
||||
/* Expects out to be an array of size 16 of Jacobian points. Fills in
|
||||
* Jacobian form (x, y, z), for O, P, 2P, ... 15P */
|
||||
void PREFIX(precompute_jac) (ecfp_jac_pt * precomp, const ecfp_aff_pt * p,
|
||||
const EC_group_fp * group) {
|
||||
int i;
|
||||
|
||||
/* fill precomputation table */
|
||||
/* set precomp[0] */
|
||||
PREFIX(set_pt_inf_jac) (&precomp[0]);
|
||||
/* set precomp[1] */
|
||||
PREFIX(copy) (precomp[1].x, p->x);
|
||||
PREFIX(copy) (precomp[1].y, p->y);
|
||||
if (PREFIX(pt_is_inf_aff) (p) == MP_YES) {
|
||||
PREFIX(zero) (precomp[1].z);
|
||||
} else {
|
||||
PREFIX(one) (precomp[1].z);
|
||||
}
|
||||
/* set precomp[2] */
|
||||
group->pt_dbl_jac(&precomp[1], &precomp[2], group);
|
||||
|
||||
/* set rest of precomp */
|
||||
for (i = 3; i < 16; i++) {
|
||||
group->pt_add_jac_aff(&precomp[i - 1], p, &precomp[i], group);
|
||||
}
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Sheueling Chang-Shantz <sheueling.chang@sun.com>,
|
||||
* Stephen Fung <fungstep@hotmail.com>, and
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
|
||||
* Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
|
||||
* Nils Larsch <nla@trustcenter.de>, and
|
||||
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
#ifdef ECL_DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* Converts a point P(px, py) from affine coordinates to Jacobian
|
||||
* projective coordinates R(rx, ry, rz). Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_set_int(rz, 1));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
|
||||
}
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
|
||||
* affine coordinates R(rx, ry). P and R can share x and y coordinates.
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int z1, z2, z3;
|
||||
|
||||
MP_DIGITS(&z1) = 0;
|
||||
MP_DIGITS(&z2) = 0;
|
||||
MP_DIGITS(&z3) = 0;
|
||||
MP_CHECKOK(mp_init(&z1));
|
||||
MP_CHECKOK(mp_init(&z2));
|
||||
MP_CHECKOK(mp_init(&z3));
|
||||
|
||||
/* if point at infinity, then set point at infinity and exit */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* transform (px, py, pz) into (px / pz^2, py / pz^3) */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&z1);
|
||||
mp_clear(&z2);
|
||||
mp_clear(&z3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Checks if point P(px, py, pz) is at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz)
|
||||
{
|
||||
return mp_cmp_z(pz);
|
||||
}
|
||||
|
||||
/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian
|
||||
* coordinates. */
|
||||
mp_err
|
||||
ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz)
|
||||
{
|
||||
mp_zero(pz);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Jacobian-affine coordinates. Assumes input is already
|
||||
* field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses equation (2) from Brown, Hankerson, Lopez, and
|
||||
* Menezes. Software Implementation of the NIST Elliptic Curves Over Prime
|
||||
* Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *qx, const mp_int *qy, mp_int *rx,
|
||||
mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int A, B, C, D, C2, C3;
|
||||
|
||||
MP_DIGITS(&A) = 0;
|
||||
MP_DIGITS(&B) = 0;
|
||||
MP_DIGITS(&C) = 0;
|
||||
MP_DIGITS(&D) = 0;
|
||||
MP_DIGITS(&C2) = 0;
|
||||
MP_DIGITS(&C3) = 0;
|
||||
MP_CHECKOK(mp_init(&A));
|
||||
MP_CHECKOK(mp_init(&B));
|
||||
MP_CHECKOK(mp_init(&C));
|
||||
MP_CHECKOK(mp_init(&D));
|
||||
MP_CHECKOK(mp_init(&C2));
|
||||
MP_CHECKOK(mp_init(&C3));
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&A);
|
||||
mp_clear(&B);
|
||||
mp_clear(&C);
|
||||
mp_clear(&D);
|
||||
mp_clear(&C2);
|
||||
mp_clear(&C3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
* This routine implements Point Doubling in the Jacobian Projective
|
||||
* space as described in the paper "Efficient elliptic curve exponentiation
|
||||
* using mixed coordinates", by H. Cohen, A Miyaji, T. Ono.
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int t0, t1, M, S;
|
||||
|
||||
MP_DIGITS(&t0) = 0;
|
||||
MP_DIGITS(&t1) = 0;
|
||||
MP_DIGITS(&M) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
MP_CHECKOK(mp_init(&t0));
|
||||
MP_CHECKOK(mp_init(&t1));
|
||||
MP_CHECKOK(mp_init(&M));
|
||||
MP_CHECKOK(mp_init(&S));
|
||||
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
/* M = 3 * px^2 + a */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_add(&t0, &group->curvea, &M, group->meth));
|
||||
} else if (mp_cmp_int(&group->curvea, -3) == 0) {
|
||||
/* M = 3 * (px + pz^2) * (px - pz^2) */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth));
|
||||
} else {
|
||||
/* M = 3 * (px^2) + a * (pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(&M, &group->curvea, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth));
|
||||
}
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
/* t0 = 4 * py^2 */
|
||||
if (mp_cmp_d(pz, 1) == 0) {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth));
|
||||
}
|
||||
|
||||
/* S = 4 * px * py^2 = px * (2 * py)^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth));
|
||||
|
||||
/* rx = M^2 - 2 * S */
|
||||
MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - 8 * py^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth));
|
||||
if (mp_isodd(&t1)) {
|
||||
MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1));
|
||||
}
|
||||
MP_CHECKOK(mp_div_2(&t1, &t1));
|
||||
MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&t0);
|
||||
mp_clear(&t1);
|
||||
mp_clear(&M);
|
||||
mp_clear(&S);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* by default, this routine is unused and thus doesn't need to be compiled */
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
|
||||
* a, b and p are the elliptic curve coefficients and the prime that
|
||||
* determines the field GFp. Elliptic curve points P and R can be
|
||||
* identical. Uses mixed Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. Uses 4-bit window method. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz;
|
||||
int i, ni, d;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
mp_zero(&precomp[0][0]);
|
||||
mp_zero(&precomp[0][1]);
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][1]));
|
||||
for (i = 2; i < 16; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0], &precomp[1][1],
|
||||
&precomp[i - 1][0], &precomp[i - 1][1],
|
||||
&precomp[i][0], &precomp[i][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(n) + 3) / 4;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
/* compute window ni */
|
||||
ni = MP_GET_BIT(n, 4 * i + 3);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 2);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i + 1);
|
||||
ni <<= 1;
|
||||
ni |= MP_GET_BIT(n, 4 * i);
|
||||
/* R = 2^4 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ni * P) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
|
||||
&rz, group));
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
|
||||
* k2 * P(x, y), where G is the generator (base point) of the group of
|
||||
* points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
|
||||
* Uses mixed Jacobian-affine coordinates. Input and output values are
|
||||
* assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
|
||||
* multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
|
||||
* Software Implementation of the NIST Elliptic Curves over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry,
|
||||
const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[4][4][2];
|
||||
mp_int rz;
|
||||
const mp_int *a, *b;
|
||||
int i, j;
|
||||
int ai, bi, d;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_DIGITS(&precomp[i][j][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][j][1]) = 0;
|
||||
}
|
||||
}
|
||||
MP_DIGITS(&rz) = 0;
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK(!((k1 == NULL)
|
||||
&& ((k2 == NULL) || (px == NULL)
|
||||
|| (py == NULL))), MP_BADARG);
|
||||
|
||||
/* if some arguments are not defined used ECPoint_mul */
|
||||
if (k1 == NULL) {
|
||||
return ECPoint_mul(group, k2, px, py, rx, ry);
|
||||
} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
|
||||
return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
|
||||
}
|
||||
|
||||
/* initialize precomputation table */
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][j][1]));
|
||||
}
|
||||
}
|
||||
|
||||
/* fill precomputation table */
|
||||
/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
|
||||
if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
|
||||
a = k2;
|
||||
b = k1;
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[1][0][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[1][0][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
|
||||
}
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
|
||||
} else {
|
||||
a = k1;
|
||||
b = k2;
|
||||
MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
|
||||
if (group->meth->field_enc) {
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(px, &precomp[0][1][0], group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_enc(py, &precomp[0][1][1], group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
|
||||
}
|
||||
}
|
||||
/* precompute [*][0][*] */
|
||||
mp_zero(&precomp[0][0][0]);
|
||||
mp_zero(&precomp[0][0][1]);
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1], group));
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[1][0][0], &precomp[1][0][1],
|
||||
&precomp[2][0][0], &precomp[2][0][1],
|
||||
&precomp[3][0][0], &precomp[3][0][1], group));
|
||||
/* precompute [*][1][*] */
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][1][0], &precomp[i][1][1], group));
|
||||
}
|
||||
/* precompute [*][2][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][2][0], &precomp[i][2][1], group));
|
||||
}
|
||||
/* precompute [*][3][*] */
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][1][0], &precomp[0][1][1],
|
||||
&precomp[0][2][0], &precomp[0][2][1],
|
||||
&precomp[0][3][0], &precomp[0][3][1], group));
|
||||
for (i = 1; i < 4; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[0][3][0], &precomp[0][3][1],
|
||||
&precomp[i][0][0], &precomp[i][0][1],
|
||||
&precomp[i][3][0], &precomp[i][3][1], group));
|
||||
}
|
||||
|
||||
d = (mpl_significant_bits(a) + 1) / 2;
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
for (i = d - 1; i >= 0; i--) {
|
||||
ai = MP_GET_BIT(a, 2 * i + 1);
|
||||
ai <<= 1;
|
||||
ai |= MP_GET_BIT(a, 2 * i);
|
||||
bi = MP_GET_BIT(b, 2 * i + 1);
|
||||
bi <<= 1;
|
||||
bi |= MP_GET_BIT(b, 2 * i);
|
||||
/* R = 2^2 * R */
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
|
||||
/* R = R + (ai * A + bi * B) */
|
||||
MP_CHECKOK(ec_GFp_pt_add_jac_aff
|
||||
(rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
|
||||
rx, ry, &rz, group));
|
||||
}
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&rz);
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mp_clear(&precomp[i][j][0]);
|
||||
mp_clear(&precomp[i][j][1]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "mplogic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_SCRATCH 6
|
||||
|
||||
/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
|
||||
* Modified Jacobian coordinates.
|
||||
*
|
||||
* Assumes input is already field-encoded using field_enc, and returns
|
||||
* output that is still field-encoded.
|
||||
*
|
||||
*/
|
||||
mp_err
|
||||
ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *t0, *t1, *M, *S;
|
||||
|
||||
t0 = &scratch[0];
|
||||
t1 = &scratch[1];
|
||||
M = &scratch[2];
|
||||
S = &scratch[3];
|
||||
|
||||
#if MAX_SCRATCH < 4
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* Check for point at infinity */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
/* Set r = pt at infinity by setting rz = 0 */
|
||||
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* M = 3 (px^2) + a*(pz^4) */
|
||||
MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth));
|
||||
|
||||
/* rz = 2 * py * pz */
|
||||
MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth));
|
||||
|
||||
/* t0 = 2y^2 , t1 = 8y^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth));
|
||||
|
||||
/* S = 4 * px * py^2 = 2 * px * t0 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(S, S, S, group->meth));
|
||||
|
||||
|
||||
/* rx = M^2 - 2S */
|
||||
MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth));
|
||||
|
||||
/* ry = M * (S - rx) - t1 */
|
||||
MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth));
|
||||
|
||||
/* ra*z^4 = 2*t1*(apz4) */
|
||||
MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth));
|
||||
|
||||
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
|
||||
* (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical.
|
||||
* Uses mixed Modified_Jacobian-affine coordinates. Assumes input is
|
||||
* already field-encoded using field_enc, and returns output that is still
|
||||
* field-encoded. */
|
||||
mp_err
|
||||
ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
||||
const mp_int *paz4, const mp_int *qx,
|
||||
const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz,
|
||||
mp_int *raz4, mp_int scratch[], const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int *A, *B, *C, *D, *C2, *C3;
|
||||
|
||||
A = &scratch[0];
|
||||
B = &scratch[1];
|
||||
C = &scratch[2];
|
||||
D = &scratch[3];
|
||||
C2 = &scratch[4];
|
||||
C3 = &scratch[5];
|
||||
|
||||
#if MAX_SCRATCH < 6
|
||||
#error "Scratch array defined too small "
|
||||
#endif
|
||||
|
||||
/* If either P or Q is the point at infinity, then return the other
|
||||
* point */
|
||||
if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
|
||||
MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
|
||||
MP_CHECKOK(mp_copy(px, rx));
|
||||
MP_CHECKOK(mp_copy(py, ry));
|
||||
MP_CHECKOK(mp_copy(pz, rz));
|
||||
MP_CHECKOK(mp_copy(paz4, raz4));
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* A = qx * pz^2, B = qy * pz^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
|
||||
|
||||
/* C2 = C^2, C3 = C^3 */
|
||||
MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));
|
||||
|
||||
/* rz = pz * C */
|
||||
MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));
|
||||
|
||||
/* C = px * C^2 */
|
||||
MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
|
||||
/* A = D^2 */
|
||||
MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));
|
||||
|
||||
/* rx = D^2 - (C^3 + 2 * (px * C^2)) */
|
||||
MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));
|
||||
|
||||
/* C3 = py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));
|
||||
|
||||
/* ry = D * (px * C^2 - rx) - py * C^3 */
|
||||
MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));
|
||||
|
||||
/* raz4 = a * rz^4 */
|
||||
MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_mul(raz4, &group->curvea, raz4, group->meth));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
|
||||
* curve points P and R can be identical. Uses mixed Modified-Jacobian
|
||||
* co-ordinates for doubling and Chudnovsky Jacobian coordinates for
|
||||
* additions. Assumes input is already field-encoded using field_enc, and
|
||||
* returns output that is still field-encoded. Uses 5-bit window NAF
|
||||
* method (algorithm 11) for scalar-point multiplication from Brown,
|
||||
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
|
||||
* Curves Over Prime Fields. */
|
||||
mp_err
|
||||
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
|
||||
mp_int *rx, mp_int *ry, const ECGroup *group)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
mp_int precomp[16][2], rz, tpx, tpy;
|
||||
mp_int raz4;
|
||||
mp_int scratch[MAX_SCRATCH];
|
||||
signed char *naf = NULL;
|
||||
int i, orderBitSize;
|
||||
|
||||
MP_DIGITS(&rz) = 0;
|
||||
MP_DIGITS(&raz4) = 0;
|
||||
MP_DIGITS(&tpx) = 0;
|
||||
MP_DIGITS(&tpy) = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_DIGITS(&precomp[i][0]) = 0;
|
||||
MP_DIGITS(&precomp[i][1]) = 0;
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_DIGITS(&scratch[i]) = 0;
|
||||
}
|
||||
|
||||
ARGCHK(group != NULL, MP_BADARG);
|
||||
ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
|
||||
|
||||
/* initialize precomputation table */
|
||||
MP_CHECKOK(mp_init(&tpx));
|
||||
MP_CHECKOK(mp_init(&tpy));;
|
||||
MP_CHECKOK(mp_init(&rz));
|
||||
MP_CHECKOK(mp_init(&raz4));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
MP_CHECKOK(mp_init(&precomp[i][0]));
|
||||
MP_CHECKOK(mp_init(&precomp[i][1]));
|
||||
}
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
MP_CHECKOK(mp_init(&scratch[i]));
|
||||
}
|
||||
|
||||
/* Set out[8] = P */
|
||||
MP_CHECKOK(mp_copy(px, &precomp[8][0]));
|
||||
MP_CHECKOK(mp_copy(py, &precomp[8][1]));
|
||||
|
||||
/* Set (tpx, tpy) = 2P */
|
||||
MP_CHECKOK(group->
|
||||
point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
|
||||
group));
|
||||
|
||||
/* Set 3P, 5P, ..., 15P */
|
||||
for (i = 8; i < 15; i++) {
|
||||
MP_CHECKOK(group->
|
||||
point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
|
||||
&precomp[i + 1][0], &precomp[i + 1][1],
|
||||
group));
|
||||
}
|
||||
|
||||
/* Set -15P, -13P, ..., -P */
|
||||
for (i = 0; i < 8; i++) {
|
||||
MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
|
||||
MP_CHECKOK(group->meth->
|
||||
field_neg(&precomp[15 - i][1], &precomp[i][1],
|
||||
group->meth));
|
||||
}
|
||||
|
||||
/* R = inf */
|
||||
MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));
|
||||
|
||||
orderBitSize = mpl_significant_bits(&group->order);
|
||||
|
||||
/* Allocate memory for NAF */
|
||||
naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
|
||||
if (naf == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Compute 5NAF */
|
||||
ec_compute_wNAF(naf, orderBitSize, n, 5);
|
||||
|
||||
/* wNAF method */
|
||||
for (i = orderBitSize; i >= 0; i--) {
|
||||
/* R = 2R */
|
||||
ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
|
||||
&raz4, scratch, group);
|
||||
if (naf[i] != 0) {
|
||||
ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
|
||||
&precomp[(naf[i] + 15) / 2][0],
|
||||
&precomp[(naf[i] + 15) / 2][1], rx, ry,
|
||||
&rz, &raz4, scratch, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* convert result S to affine coordinates */
|
||||
MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
|
||||
|
||||
CLEANUP:
|
||||
for (i = 0; i < MAX_SCRATCH; i++) {
|
||||
mp_clear(&scratch[i]);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
mp_clear(&precomp[i][0]);
|
||||
mp_clear(&precomp[i][1]);
|
||||
}
|
||||
mp_clear(&tpx);
|
||||
mp_clear(&tpy);
|
||||
mp_clear(&rz);
|
||||
mp_clear(&raz4);
|
||||
free(naf);
|
||||
return res;
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for
|
||||
* code implementation. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpi-priv.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ecp.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Construct a generic GFMethod for arithmetic over prime fields with
|
||||
* irreducible irr. */
|
||||
GFMethod *
|
||||
GFMethod_consGFp_mont(const mp_int *irr)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
int i;
|
||||
GFMethod *meth = NULL;
|
||||
mp_mont_modulus *mmm;
|
||||
|
||||
meth = GFMethod_consGFp(irr);
|
||||
if (meth == NULL)
|
||||
return NULL;
|
||||
|
||||
mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus));
|
||||
if (mmm == NULL) {
|
||||
res = MP_MEM;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
meth->field_mul = &ec_GFp_mul_mont;
|
||||
meth->field_sqr = &ec_GFp_sqr_mont;
|
||||
meth->field_div = &ec_GFp_div_mont;
|
||||
meth->field_enc = &ec_GFp_enc_mont;
|
||||
meth->field_dec = &ec_GFp_dec_mont;
|
||||
meth->extra1 = mmm;
|
||||
meth->extra2 = NULL;
|
||||
meth->extra_free = &ec_GFp_extra_free_mont;
|
||||
|
||||
mmm->N = meth->irr;
|
||||
i = mpl_significant_bits(&meth->irr);
|
||||
i += MP_DIGIT_BIT - 1;
|
||||
mmm->b = i - i % MP_DIGIT_BIT;
|
||||
mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0));
|
||||
|
||||
CLEANUP:
|
||||
if (res != MP_OKAY) {
|
||||
GFMethod_free(meth);
|
||||
return NULL;
|
||||
}
|
||||
return meth;
|
||||
}
|
||||
|
||||
/* Wrapper functions for generic prime field arithmetic. */
|
||||
|
||||
/* Field multiplication using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
#ifdef MP_MONT_USE_MP_MUL
|
||||
/* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont
|
||||
* is not implemented and we have to use mp_mul and s_mp_redc directly
|
||||
*/
|
||||
MP_CHECKOK(mp_mul(a, b, r));
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
#else
|
||||
mp_int s;
|
||||
|
||||
MP_DIGITS(&s) = 0;
|
||||
/* s_mp_mul_mont doesn't allow source and destination to be the same */
|
||||
if ((a == r) || (b == r)) {
|
||||
MP_CHECKOK(mp_init(&s));
|
||||
MP_CHECKOK(s_mp_mul_mont
|
||||
(a, b, &s, (mp_mont_modulus *) meth->extra1));
|
||||
MP_CHECKOK(mp_copy(&s, r));
|
||||
mp_clear(&s);
|
||||
} else {
|
||||
return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1);
|
||||
}
|
||||
#endif
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Field squaring using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
return ec_GFp_mul_mont(a, a, r, meth);
|
||||
}
|
||||
|
||||
/* Field division using Montgomery reduction. */
|
||||
mp_err
|
||||
ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r,
|
||||
const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* if A=aZ represents a encoded in montgomery coordinates with Z and #
|
||||
* and \ respectively represent multiplication and division in
|
||||
* montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv =
|
||||
* (1/b)Z = (1/B)(Z^2) where B # Binv = Z */
|
||||
MP_CHECKOK(ec_GFp_div(a, b, r, meth));
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
if (a == NULL) {
|
||||
MP_CHECKOK(ec_GFp_enc_mont(r, r, meth));
|
||||
}
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Encode a field element in Montgomery form. See s_mp_to_mont in
|
||||
* mpi/mpmontg.c */
|
||||
mp_err
|
||||
ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_mont_modulus *mmm;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
mmm = (mp_mont_modulus *) meth->extra1;
|
||||
MP_CHECKOK(mpl_lsh(a, r, mmm->b));
|
||||
MP_CHECKOK(mp_mod(r, &mmm->N, r));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Decode a field element from Montgomery form. */
|
||||
mp_err
|
||||
ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth)
|
||||
{
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
if (a != r) {
|
||||
MP_CHECKOK(mp_copy(a, r));
|
||||
}
|
||||
MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1));
|
||||
CLEANUP:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Free the memory allocated to the extra fields of Montgomery GFMethod
|
||||
* object. */
|
||||
void
|
||||
ec_GFp_extra_free_mont(GFMethod *meth)
|
||||
{
|
||||
if (meth->extra1 != NULL) {
|
||||
free(meth->extra1);
|
||||
meth->extra1 = NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,516 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for binary polynomial field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpprime.h"
|
||||
#include "mp_gf2m.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ec2.h"
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) { \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ op; } \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
dUserTime = dNow-dStart; \
|
||||
if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Test curve using generic field arithmetic. */
|
||||
#define ECTEST_GENERIC_GF2M(name_c, name) \
|
||||
printf("Testing %s using generic implementation...\n", name_c); \
|
||||
params = EC_GetNamedCurveParams(name); \
|
||||
if (params == NULL) { \
|
||||
printf(" Error: could not construct params.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromHex(params); \
|
||||
if (group == NULL) { \
|
||||
printf(" Error: could not construct group.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 1) ); \
|
||||
printf("... okay.\n");
|
||||
|
||||
/* Test curve using specific field arithmetic. */
|
||||
#define ECTEST_NAMED_GF2M(name_c, name) \
|
||||
printf("Testing %s using specific implementation...\n", name_c); \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromName(name); \
|
||||
if (group == NULL) { \
|
||||
printf(" Warning: could not construct group.\n"); \
|
||||
printf("... failed; continuing with remaining tests.\n"); \
|
||||
} else { \
|
||||
MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 0) ); \
|
||||
printf("... okay.\n"); \
|
||||
}
|
||||
|
||||
/* Performs basic tests of elliptic curve cryptography over binary
|
||||
* polynomial fields. If tests fail, then it prints an error message,
|
||||
* aborts, and returns an error code. Otherwise, returns 0. */
|
||||
int
|
||||
ectest_curve_GF2m(ECGroup *group, int ectestPrint, int ectestTime,
|
||||
int generic)
|
||||
{
|
||||
|
||||
mp_int one, order_1, gx, gy, rx, ry, n;
|
||||
int size;
|
||||
mp_err res;
|
||||
char s[1000];
|
||||
|
||||
/* initialize values */
|
||||
MP_CHECKOK(mp_init(&one));
|
||||
MP_CHECKOK(mp_init(&order_1));
|
||||
MP_CHECKOK(mp_init(&gx));
|
||||
MP_CHECKOK(mp_init(&gy));
|
||||
MP_CHECKOK(mp_init(&rx));
|
||||
MP_CHECKOK(mp_init(&ry));
|
||||
MP_CHECKOK(mp_init(&n));
|
||||
|
||||
MP_CHECKOK(mp_set_int(&one, 1));
|
||||
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
|
||||
|
||||
/* encode base point */
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&group->genx, &gx));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &gy));
|
||||
}
|
||||
|
||||
if (ectestPrint) {
|
||||
/* output base point */
|
||||
printf(" base point P:\n");
|
||||
MP_CHECKOK(mp_toradix(&gx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&gy, s, 16));
|
||||
printf(" %s\n", s);
|
||||
if (group->meth->field_enc) {
|
||||
printf(" base point P (encoded):\n");
|
||||
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_aff
|
||||
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0)
|
||||
|| (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_mont
|
||||
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (montgomery):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0)
|
||||
|| (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_proj
|
||||
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (projective):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0)
|
||||
|| (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_aff
|
||||
(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_mont
|
||||
(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (montgomery):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GF2M_PROJ
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GF2m_pt_mul_proj
|
||||
(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (projective):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* check that (order-1)P + (order-1)P + P == (order-1)P */
|
||||
MP_CHECKOK(ECPoints_mul
|
||||
(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
|
||||
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf
|
||||
(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* test validate_point function */
|
||||
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
|
||||
printf(" Error: validate point on base point failed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
|
||||
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
|
||||
printf(" Error: validate point on invalid point passed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (ectestTime) {
|
||||
/* compute random scalar */
|
||||
size = mpl_significant_bits(&group->meth->irr);
|
||||
if (size < MP_OKAY) {
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
|
||||
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
|
||||
/* timed test */
|
||||
if (generic) {
|
||||
#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ec_GF2m_pt_mul_aff
|
||||
(&n, &group->genx, &group->geny, &rx, &ry,
|
||||
group)), 100);
|
||||
#endif
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoints_mul
|
||||
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
} else {
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoints_mul
|
||||
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&one);
|
||||
mp_clear(&order_1);
|
||||
mp_clear(&gx);
|
||||
mp_clear(&gy);
|
||||
mp_clear(&rx);
|
||||
mp_clear(&ry);
|
||||
mp_clear(&n);
|
||||
if (res != MP_OKAY) {
|
||||
printf(" Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Prints help information. */
|
||||
void
|
||||
printUsage()
|
||||
{
|
||||
printf("Usage: ecp_test [--print] [--time]\n");
|
||||
printf
|
||||
(" --print Print out results of each point arithmetic test.\n");
|
||||
printf
|
||||
(" --time Benchmark point operations and print results.\n");
|
||||
}
|
||||
|
||||
/* Performs tests of elliptic curve cryptography over binary polynomial
|
||||
* fields. If tests fail, then it prints an error message, aborts, and
|
||||
* returns an error code. Otherwise, returns 0. */
|
||||
int
|
||||
main(int argv, char **argc)
|
||||
{
|
||||
|
||||
int ectestTime = 0;
|
||||
int ectestPrint = 0;
|
||||
int i;
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res;
|
||||
|
||||
/* read command-line arguments */
|
||||
for (i = 1; i < argv; i++) {
|
||||
if ((strcasecmp(argc[i], "time") == 0)
|
||||
|| (strcasecmp(argc[i], "-time") == 0)
|
||||
|| (strcasecmp(argc[i], "--time") == 0)) {
|
||||
ectestTime = 1;
|
||||
} else if ((strcasecmp(argc[i], "print") == 0)
|
||||
|| (strcasecmp(argc[i], "-print") == 0)
|
||||
|| (strcasecmp(argc[i], "--print") == 0)) {
|
||||
ectestPrint = 1;
|
||||
} else {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* generic arithmetic tests */
|
||||
ECTEST_GENERIC_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
|
||||
|
||||
/* specific arithmetic tests */
|
||||
ECTEST_NAMED_GF2M("NIST-K163", ECCurve_NIST_K163);
|
||||
ECTEST_NAMED_GF2M("NIST-B163", ECCurve_NIST_B163);
|
||||
ECTEST_NAMED_GF2M("NIST-K233", ECCurve_NIST_K233);
|
||||
ECTEST_NAMED_GF2M("NIST-B233", ECCurve_NIST_B233);
|
||||
ECTEST_NAMED_GF2M("NIST-K283", ECCurve_NIST_K283);
|
||||
ECTEST_NAMED_GF2M("NIST-B283", ECCurve_NIST_B283);
|
||||
ECTEST_NAMED_GF2M("NIST-K409", ECCurve_NIST_K409);
|
||||
ECTEST_NAMED_GF2M("NIST-B409", ECCurve_NIST_B409);
|
||||
ECTEST_NAMED_GF2M("NIST-K571", ECCurve_NIST_K571);
|
||||
ECTEST_NAMED_GF2M("NIST-B571", ECCurve_NIST_B571);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V1", ECCurve_X9_62_CHAR2_PNB163V1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V2", ECCurve_X9_62_CHAR2_PNB163V2);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V3", ECCurve_X9_62_CHAR2_PNB163V3);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB176V1", ECCurve_X9_62_CHAR2_PNB176V1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V1", ECCurve_X9_62_CHAR2_TNB191V1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V2", ECCurve_X9_62_CHAR2_TNB191V2);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V3", ECCurve_X9_62_CHAR2_TNB191V3);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB208W1", ECCurve_X9_62_CHAR2_PNB208W1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V1", ECCurve_X9_62_CHAR2_TNB239V1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V2", ECCurve_X9_62_CHAR2_TNB239V2);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V3", ECCurve_X9_62_CHAR2_TNB239V3);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB272W1", ECCurve_X9_62_CHAR2_PNB272W1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB304W1", ECCurve_X9_62_CHAR2_PNB304W1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB359V1", ECCurve_X9_62_CHAR2_TNB359V1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB368W1", ECCurve_X9_62_CHAR2_PNB368W1);
|
||||
ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB431R1", ECCurve_X9_62_CHAR2_TNB431R1);
|
||||
ECTEST_NAMED_GF2M("SECT-113R1", ECCurve_SECG_CHAR2_113R1);
|
||||
ECTEST_NAMED_GF2M("SECT-113R2", ECCurve_SECG_CHAR2_113R2);
|
||||
ECTEST_NAMED_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1);
|
||||
ECTEST_NAMED_GF2M("SECT-131R2", ECCurve_SECG_CHAR2_131R2);
|
||||
ECTEST_NAMED_GF2M("SECT-163K1", ECCurve_SECG_CHAR2_163K1);
|
||||
ECTEST_NAMED_GF2M("SECT-163R1", ECCurve_SECG_CHAR2_163R1);
|
||||
ECTEST_NAMED_GF2M("SECT-163R2", ECCurve_SECG_CHAR2_163R2);
|
||||
ECTEST_NAMED_GF2M("SECT-193R1", ECCurve_SECG_CHAR2_193R1);
|
||||
ECTEST_NAMED_GF2M("SECT-193R2", ECCurve_SECG_CHAR2_193R2);
|
||||
ECTEST_NAMED_GF2M("SECT-233K1", ECCurve_SECG_CHAR2_233K1);
|
||||
ECTEST_NAMED_GF2M("SECT-233R1", ECCurve_SECG_CHAR2_233R1);
|
||||
ECTEST_NAMED_GF2M("SECT-239K1", ECCurve_SECG_CHAR2_239K1);
|
||||
ECTEST_NAMED_GF2M("SECT-283K1", ECCurve_SECG_CHAR2_283K1);
|
||||
ECTEST_NAMED_GF2M("SECT-283R1", ECCurve_SECG_CHAR2_283R1);
|
||||
ECTEST_NAMED_GF2M("SECT-409K1", ECCurve_SECG_CHAR2_409K1);
|
||||
ECTEST_NAMED_GF2M("SECT-409R1", ECCurve_SECG_CHAR2_409R1);
|
||||
ECTEST_NAMED_GF2M("SECT-571K1", ECCurve_SECG_CHAR2_571K1);
|
||||
ECTEST_NAMED_GF2M("SECT-571R1", ECCurve_SECG_CHAR2_571R1);
|
||||
ECTEST_NAMED_GF2M("WTLS-1 (113)", ECCurve_WTLS_1);
|
||||
ECTEST_NAMED_GF2M("WTLS-3 (163)", ECCurve_WTLS_3);
|
||||
ECTEST_NAMED_GF2M("WTLS-4 (113)", ECCurve_WTLS_4);
|
||||
ECTEST_NAMED_GF2M("WTLS-5 (163)", ECCurve_WTLS_5);
|
||||
ECTEST_NAMED_GF2M("WTLS-10 (233)", ECCurve_WTLS_10);
|
||||
ECTEST_NAMED_GF2M("WTLS-11 (233)", ECCurve_WTLS_11);
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
ECGroup_free(group);
|
||||
if (res != MP_OKAY) {
|
||||
printf("Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int ec_twoTo(int e);
|
||||
|
||||
/* Number of bits of scalar to test */
|
||||
#define BITSIZE 160
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) { \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ op; } \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
dUserTime = dNow-dStart; \
|
||||
if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D.
|
||||
* Hankerson, J. Hernandez and A. Menezes, "Software implementation of
|
||||
* elliptic curve cryptography over binary fields", Proc. CHES 2000. */
|
||||
|
||||
mp_err
|
||||
main(void)
|
||||
{
|
||||
signed char naf[BITSIZE + 1];
|
||||
ECGroup *group = NULL;
|
||||
mp_int k;
|
||||
mp_int *scalar;
|
||||
int i, count;
|
||||
int res;
|
||||
int w = 5;
|
||||
char s[1000];
|
||||
|
||||
/* Get a 160 bit scalar to compute wNAF from */
|
||||
group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
|
||||
scalar = &group->genx;
|
||||
|
||||
/* Compute wNAF representation of scalar */
|
||||
ec_compute_wNAF(naf, BITSIZE, scalar, w);
|
||||
|
||||
/* Verify correctness of representation */
|
||||
mp_init(&k); /* init k to 0 */
|
||||
|
||||
for (i = BITSIZE; i >= 0; i--) {
|
||||
mp_add(&k, &k, &k);
|
||||
/* digits in mp_???_d are unsigned */
|
||||
if (naf[i] >= 0) {
|
||||
mp_add_d(&k, naf[i], &k);
|
||||
} else {
|
||||
mp_sub_d(&k, -naf[i], &k);
|
||||
}
|
||||
}
|
||||
|
||||
if (mp_cmp(&k, scalar) != 0) {
|
||||
printf("Error: incorrect NAF value.\n");
|
||||
MP_CHECKOK(mp_toradix(&k, s, 16));
|
||||
printf("NAF value %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(scalar, s, 16));
|
||||
printf("original value %s\n", s);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Verify digits of representation are valid */
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] % 2 == 0 && naf[i] != 0) {
|
||||
printf("Error: Even non-zero digit found.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
|
||||
printf("Error: Magnitude of naf digit too large.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify sparsity of representation */
|
||||
count = w - 1;
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] != 0) {
|
||||
if (count < w - 1) {
|
||||
printf("Error: Sparsity failed.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
count = 0;
|
||||
} else
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Check timing */
|
||||
M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
|
||||
|
||||
printf("Test passed.\n");
|
||||
CLEANUP:
|
||||
ECGroup_free(group);
|
||||
return MP_OKAY;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,460 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the elliptic curve math library for prime field curves.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Sun Microsystems, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpprime.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecp.h"
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) { \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ op; } \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \
|
||||
dUserTime = dNow-dStart; \
|
||||
if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Test curve using generic field arithmetic. */
|
||||
#define ECTEST_GENERIC_GFP(name_c, name) \
|
||||
printf("Testing %s using generic implementation...\n", name_c); \
|
||||
params = EC_GetNamedCurveParams(name); \
|
||||
if (params == NULL) { \
|
||||
printf(" Error: could not construct params.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromHex(params); \
|
||||
if (group == NULL) { \
|
||||
printf(" Error: could not construct group.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 1) ); \
|
||||
printf("... okay.\n");
|
||||
|
||||
/* Test curve using specific field arithmetic. */
|
||||
#define ECTEST_NAMED_GFP(name_c, name) \
|
||||
printf("Testing %s using specific implementation...\n", name_c); \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromName(name); \
|
||||
if (group == NULL) { \
|
||||
printf(" Warning: could not construct group.\n"); \
|
||||
printf("... failed; continuing with remaining tests.\n"); \
|
||||
} else { \
|
||||
MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 0) ); \
|
||||
printf("... okay.\n"); \
|
||||
}
|
||||
|
||||
/* Performs basic tests of elliptic curve cryptography over prime fields.
|
||||
* If tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
|
||||
int generic)
|
||||
{
|
||||
|
||||
mp_int one, order_1, gx, gy, rx, ry, n;
|
||||
int size;
|
||||
mp_err res;
|
||||
char s[1000];
|
||||
|
||||
/* initialize values */
|
||||
MP_CHECKOK(mp_init(&one));
|
||||
MP_CHECKOK(mp_init(&order_1));
|
||||
MP_CHECKOK(mp_init(&gx));
|
||||
MP_CHECKOK(mp_init(&gy));
|
||||
MP_CHECKOK(mp_init(&rx));
|
||||
MP_CHECKOK(mp_init(&ry));
|
||||
MP_CHECKOK(mp_init(&n));
|
||||
|
||||
MP_CHECKOK(mp_set_int(&one, 1));
|
||||
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
|
||||
|
||||
/* encode base point */
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&group->genx, &gx));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &gy));
|
||||
}
|
||||
if (ectestPrint) {
|
||||
/* output base point */
|
||||
printf(" base point P:\n");
|
||||
MP_CHECKOK(mp_toradix(&gx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&gy, s, 16));
|
||||
printf(" %s\n", s);
|
||||
if (group->meth->field_enc) {
|
||||
printf(" base point P (encoded):\n");
|
||||
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff
|
||||
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0)
|
||||
|| (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac
|
||||
(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0)
|
||||
|| (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff
|
||||
(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac
|
||||
(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* check that (order-1)P + (order-1)P + P == (order-1)P */
|
||||
MP_CHECKOK(ECPoints_mul
|
||||
(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
|
||||
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf
|
||||
(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* test validate_point function */
|
||||
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
|
||||
printf(" Error: validate point on base point failed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
|
||||
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
|
||||
printf(" Error: validate point on invalid point passed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (ectestTime) {
|
||||
/* compute random scalar */
|
||||
size = mpl_significant_bits(&group->meth->irr);
|
||||
if (size < MP_OKAY) {
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
|
||||
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
|
||||
/* timed test */
|
||||
if (generic) {
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ec_GFp_pt_mul_aff
|
||||
(&n, &group->genx, &group->geny, &rx, &ry,
|
||||
group)), 100);
|
||||
#endif
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoints_mul
|
||||
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
} else {
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK
|
||||
(ECPoints_mul
|
||||
(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&one);
|
||||
mp_clear(&order_1);
|
||||
mp_clear(&gx);
|
||||
mp_clear(&gy);
|
||||
mp_clear(&rx);
|
||||
mp_clear(&ry);
|
||||
mp_clear(&n);
|
||||
if (res != MP_OKAY) {
|
||||
printf(" Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Prints help information. */
|
||||
void
|
||||
printUsage()
|
||||
{
|
||||
printf("Usage: ecp_test [--print] [--time]\n");
|
||||
printf
|
||||
(" --print Print out results of each point arithmetic test.\n");
|
||||
printf
|
||||
(" --time Benchmark point operations and print results.\n");
|
||||
}
|
||||
|
||||
/* Performs tests of elliptic curve cryptography over prime fields If
|
||||
* tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
main(int argv, char **argc)
|
||||
{
|
||||
|
||||
int ectestTime = 0;
|
||||
int ectestPrint = 0;
|
||||
int i;
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res;
|
||||
|
||||
/* read command-line arguments */
|
||||
for (i = 1; i < argv; i++) {
|
||||
if ((strcasecmp(argc[i], "time") == 0)
|
||||
|| (strcasecmp(argc[i], "-time") == 0)
|
||||
|| (strcasecmp(argc[i], "--time") == 0)) {
|
||||
ectestTime = 1;
|
||||
} else if ((strcasecmp(argc[i], "print") == 0)
|
||||
|| (strcasecmp(argc[i], "-print") == 0)
|
||||
|| (strcasecmp(argc[i], "--print") == 0)) {
|
||||
ectestPrint = 1;
|
||||
} else {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* generic arithmetic tests */
|
||||
ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
|
||||
/* specific arithmetic tests */
|
||||
ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
|
||||
ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
|
||||
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
|
||||
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
|
||||
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
|
||||
ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
|
||||
ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
|
||||
ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
|
||||
ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
|
||||
ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
|
||||
ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
|
||||
ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
|
||||
ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
|
||||
ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
|
||||
ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
|
||||
ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
|
||||
ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
|
||||
ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
|
||||
ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
|
||||
ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
|
||||
ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
|
||||
ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
|
||||
ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
|
||||
ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
ECGroup_free(group);
|
||||
if (res != MP_OKAY) {
|
||||
printf("Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
;+#
|
||||
;+# ***** BEGIN LICENSE BLOCK *****
|
||||
;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
;+#
|
||||
;+# The contents of this file are subject to the Mozilla Public License Version
|
||||
;+# 1.1 (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.mozilla.org/MPL/
|
||||
;+#
|
||||
;+# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
;+# for the specific language governing rights and limitations under the
|
||||
;+# License.
|
||||
;+#
|
||||
;+# The Original Code is the Netscape security libraries.
|
||||
;+#
|
||||
;+# The Initial Developer of the Original Code is
|
||||
;+# Netscape Communications Corporation.
|
||||
;+# Portions created by the Initial Developer are Copyright (C) 2000
|
||||
;+# the Initial Developer. All Rights Reserved.
|
||||
;+#
|
||||
;+# Contributor(s):
|
||||
;+#
|
||||
;+# Alternatively, the contents of this file may be used under the terms of
|
||||
;+# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
;+# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
;+# of those above. If you wish to allow use of your version of this file only
|
||||
;+# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
;+# use your version of this file under the terms of the MPL, indicate your
|
||||
;+# decision by deleting the provisions above and replace them with the notice
|
||||
;+# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
;+# the provisions above, a recipient may use your version of this file under
|
||||
;+# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
;+#
|
||||
;+# ***** END LICENSE BLOCK *****
|
||||
;+#
|
||||
;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
|
||||
;+# 1. For all unix platforms, the string ";-" means "remove this line"
|
||||
;+# 2. For all unix platforms, the string " DATA " will be removed from any
|
||||
;+# line on which it occurs.
|
||||
;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
|
||||
;+# On AIX, lines containing ";+" will be removed.
|
||||
;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
|
||||
;+# 5. For all unix platforms, after the above processing has taken place,
|
||||
;+# all characters after the first ";" on the line will be removed.
|
||||
;+# And for AIX, the first ";" will also be removed.
|
||||
;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
|
||||
;+# directives are hidden behind ";", ";+", and ";-"
|
||||
;+
|
||||
;+NSSprivate_3.11 { # NSS 3.11 release
|
||||
;+ global:
|
||||
LIBRARY freebl3 ;-
|
||||
EXPORTS ;-
|
||||
FREEBL_GetVector;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
@@ -1,100 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "softkver.h"
|
||||
#include <winver.h>
|
||||
|
||||
#define MY_LIBNAME "freebl"
|
||||
#define MY_FILEDESCRIPTION "NSS freebl Library"
|
||||
|
||||
#define STRINGIZE(x) #x
|
||||
#define STRINGIZE2(x) STRINGIZE(x)
|
||||
#define SOFTOKEN_VMAJOR_STR STRINGIZE2(SOFTOKEN_VMAJOR)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define MY_DEBUG_STR " (debug)"
|
||||
#define MY_FILEFLAGS_1 VS_FF_DEBUG
|
||||
#else
|
||||
#define MY_DEBUG_STR ""
|
||||
#define MY_FILEFLAGS_1 0x0L
|
||||
#endif
|
||||
#if SOFTOKEN_BETA
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE
|
||||
#else
|
||||
#define MY_FILEFLAGS_2 MY_FILEFLAGS_1
|
||||
#endif
|
||||
|
||||
#ifdef WINNT
|
||||
#define MY_FILEOS VOS_NT_WINDOWS32
|
||||
#else
|
||||
#define MY_FILEOS VOS__WINDOWS32
|
||||
#endif
|
||||
|
||||
#define MY_INTERNAL_NAME MY_LIBNAME SOFTOKEN_VMAJOR_STR
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version-information resource
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SOFTOKEN_VMAJOR,SOFTOKEN_VMINOR,SOFTOKEN_VPATCH,0
|
||||
PRODUCTVERSION SOFTOKEN_VMAJOR,SOFTOKEN_VMINOR,SOFTOKEN_VPATCH,0
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
FILEFLAGS MY_FILEFLAGS_2
|
||||
FILEOS MY_FILEOS
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE 0x0L // not used
|
||||
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904B0" // Lang=US English, CharSet=Unicode
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Mozilla Foundation\0"
|
||||
VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0"
|
||||
VALUE "FileVersion", SOFTOKEN_VERSION "\0"
|
||||
VALUE "InternalName", MY_INTERNAL_NAME "\0"
|
||||
VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0"
|
||||
VALUE "ProductName", "Network Security Services\0"
|
||||
VALUE "ProductVersion", SOFTOKEN_VERSION "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
@@ -1,56 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* Library identity and versioning */
|
||||
|
||||
#include "softkver.h"
|
||||
|
||||
#if defined(DEBUG)
|
||||
#define _DEBUG_STRING " (debug)"
|
||||
#else
|
||||
#define _DEBUG_STRING ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Version information for the 'ident' and 'what commands
|
||||
*
|
||||
* NOTE: the first component of the concatenated rcsid string
|
||||
* must not end in a '$' to prevent rcs keyword substitution.
|
||||
*/
|
||||
const char __nss_freebl_rcsid[] = "$Header: NSS " SOFTOKEN_VERSION _DEBUG_STRING
|
||||
" " __DATE__ " " __TIME__ " $";
|
||||
const char __nss_freebl_sccsid[] = "@(#)NSS " SOFTOKEN_VERSION _DEBUG_STRING
|
||||
" " __DATE__ " " __TIME__;
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
* Kai Engert <kengert@redhat.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* This file is meant to be included by other .c files.
|
||||
* This file takes a "parameter", the scope which includes this
|
||||
* code shall declare this variable:
|
||||
* const char *NameOfThisSharedLib;
|
||||
*
|
||||
* NameOfThisSharedLib:
|
||||
* The file name of the shared library that shall be used as the
|
||||
* "reference library". The loader will attempt to load the requested
|
||||
* library from the same directory as the reference library.
|
||||
*/
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#include <unistd.h>
|
||||
#define BL_MAXSYMLINKS 20
|
||||
|
||||
/*
|
||||
* If 'link' is a symbolic link, this function follows the symbolic links
|
||||
* and returns the pathname of the ultimate source of the symbolic links.
|
||||
* If 'link' is not a symbolic link, this function returns NULL.
|
||||
* The caller should call PR_Free to free the string returned by this
|
||||
* function.
|
||||
*/
|
||||
static char* loader_GetOriginalPathname(const char* link)
|
||||
{
|
||||
char* resolved = NULL;
|
||||
char* input = NULL;
|
||||
PRUint32 iterations = 0;
|
||||
PRInt32 len = 0, retlen = 0;
|
||||
if (!link) {
|
||||
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
|
||||
return NULL;
|
||||
}
|
||||
len = PR_MAX(1024, strlen(link) + 1);
|
||||
resolved = PR_Malloc(len);
|
||||
input = PR_Malloc(len);
|
||||
if (!resolved || !input) {
|
||||
if (resolved) {
|
||||
PR_Free(resolved);
|
||||
}
|
||||
if (input) {
|
||||
PR_Free(input);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
strcpy(input, link);
|
||||
while ( (iterations++ < BL_MAXSYMLINKS) &&
|
||||
( (retlen = readlink(input, resolved, len - 1)) > 0) ) {
|
||||
char* tmp = input;
|
||||
resolved[retlen] = '\0'; /* NULL termination */
|
||||
input = resolved;
|
||||
resolved = tmp;
|
||||
}
|
||||
PR_Free(resolved);
|
||||
if (iterations == 1 && retlen < 0) {
|
||||
PR_Free(input);
|
||||
input = NULL;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
/*
|
||||
* Load the library with the file name 'name' residing in the same
|
||||
* directory as the reference library, whose pathname is 'referencePath'.
|
||||
*/
|
||||
static PRLibrary *
|
||||
loader_LoadLibInReferenceDir(const char *referencePath, const char *name)
|
||||
{
|
||||
PRLibrary *dlh = NULL;
|
||||
char *fullName = NULL;
|
||||
char* c;
|
||||
PRLibSpec libSpec;
|
||||
|
||||
/* Remove the trailing filename from referencePath and add the new one */
|
||||
c = strrchr(referencePath, PR_GetDirectorySeparator());
|
||||
if (c) {
|
||||
size_t referencePathSize = 1 + c - referencePath;
|
||||
fullName = (char*) PORT_Alloc(strlen(name) + referencePathSize + 1);
|
||||
if (fullName) {
|
||||
memcpy(fullName, referencePath, referencePathSize);
|
||||
strcpy(fullName + referencePathSize, name);
|
||||
#ifdef DEBUG_LOADER
|
||||
PR_fprintf(PR_STDOUT, "\nAttempting to load fully-qualified %s\n",
|
||||
fullName);
|
||||
#endif
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
libSpec.value.pathname = fullName;
|
||||
dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
PORT_Free(fullName);
|
||||
}
|
||||
}
|
||||
return dlh;
|
||||
}
|
||||
|
||||
/*
|
||||
* We use PR_GetLibraryFilePathname to get the pathname of the loaded
|
||||
* shared lib that contains this function, and then do a PR_LoadLibrary
|
||||
* with an absolute pathname for the softoken shared library.
|
||||
*/
|
||||
|
||||
static PRLibrary *
|
||||
loader_LoadLibrary(const char *nameToLoad)
|
||||
{
|
||||
PRLibrary *lib = NULL;
|
||||
char* fullPath = NULL;
|
||||
PRLibSpec libSpec;
|
||||
|
||||
/* Get the pathname for nameOfAlreadyLoadedLib, i.e. /usr/lib/libnss3.so
|
||||
* PR_GetLibraryFilePathname works with either the base library name or a
|
||||
* function pointer, depending on the platform. We can't query an exported
|
||||
* symbol such as NSC_GetFunctionList, because on some platforms we can't
|
||||
* find symbols in loaded implicit dependencies.
|
||||
* But we can just get the address of this function !
|
||||
*/
|
||||
fullPath = PR_GetLibraryFilePathname(NameOfThisSharedLib,
|
||||
&loader_LoadLibrary);
|
||||
|
||||
if (fullPath) {
|
||||
lib = loader_LoadLibInReferenceDir(fullPath, nameToLoad);
|
||||
#ifdef XP_UNIX
|
||||
if (!lib) {
|
||||
/*
|
||||
* If fullPath is a symbolic link, resolve the symbolic
|
||||
* link and try again.
|
||||
*/
|
||||
char* originalfullPath = loader_GetOriginalPathname(fullPath);
|
||||
if (originalfullPath) {
|
||||
PR_Free(fullPath);
|
||||
fullPath = originalfullPath;
|
||||
lib = loader_LoadLibInReferenceDir(fullPath, nameToLoad);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
PR_Free(fullPath);
|
||||
}
|
||||
if (!lib) {
|
||||
#ifdef DEBUG_LOADER
|
||||
PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", nameToLoad);
|
||||
#endif
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
libSpec.value.pathname = nameToLoad;
|
||||
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL);
|
||||
}
|
||||
if (NULL == lib) {
|
||||
#ifdef DEBUG_LOADER
|
||||
PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", nameToLoad);
|
||||
#endif
|
||||
}
|
||||
return lib;
|
||||
}
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* ldvector.c - platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: ldvector.c,v 1.16 2007-11-09 18:49:32 wtc%google.com Exp $ */
|
||||
|
||||
#include "loader.h"
|
||||
#include "alghmac.h"
|
||||
|
||||
static const struct FREEBLVectorStr vector =
|
||||
{
|
||||
|
||||
sizeof vector,
|
||||
FREEBL_VERSION,
|
||||
|
||||
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,
|
||||
|
||||
/* End of Version 3.001. */
|
||||
|
||||
RSA_PrivateKeyOpDoubleChecked,
|
||||
RSA_PrivateKeyCheck,
|
||||
BL_Cleanup,
|
||||
|
||||
/* End of Version 3.002. */
|
||||
|
||||
SHA256_NewContext,
|
||||
SHA256_DestroyContext,
|
||||
SHA256_Begin,
|
||||
SHA256_Update,
|
||||
SHA256_End,
|
||||
SHA256_HashBuf,
|
||||
SHA256_Hash,
|
||||
SHA256_TraceState,
|
||||
SHA256_FlattenSize,
|
||||
SHA256_Flatten,
|
||||
SHA256_Resurrect,
|
||||
|
||||
SHA512_NewContext,
|
||||
SHA512_DestroyContext,
|
||||
SHA512_Begin,
|
||||
SHA512_Update,
|
||||
SHA512_End,
|
||||
SHA512_HashBuf,
|
||||
SHA512_Hash,
|
||||
SHA512_TraceState,
|
||||
SHA512_FlattenSize,
|
||||
SHA512_Flatten,
|
||||
SHA512_Resurrect,
|
||||
|
||||
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.003. */
|
||||
|
||||
AESKeyWrap_CreateContext,
|
||||
AESKeyWrap_DestroyContext,
|
||||
AESKeyWrap_Encrypt,
|
||||
AESKeyWrap_Decrypt,
|
||||
|
||||
/* End of Version 3.004. */
|
||||
|
||||
BLAPI_SHVerify,
|
||||
BLAPI_VerifySelf,
|
||||
|
||||
/* End of Version 3.005. */
|
||||
|
||||
EC_NewKey,
|
||||
EC_NewKeyFromSeed,
|
||||
EC_ValidatePublicKey,
|
||||
ECDH_Derive,
|
||||
ECDSA_SignDigest,
|
||||
ECDSA_VerifyDigest,
|
||||
ECDSA_SignDigestWithSeed,
|
||||
|
||||
/* End of Version 3.006. */
|
||||
/* End of Version 3.007. */
|
||||
|
||||
AES_InitContext,
|
||||
AESKeyWrap_InitContext,
|
||||
DES_InitContext,
|
||||
RC2_InitContext,
|
||||
RC4_InitContext,
|
||||
|
||||
AES_AllocateContext,
|
||||
AESKeyWrap_AllocateContext,
|
||||
DES_AllocateContext,
|
||||
RC2_AllocateContext,
|
||||
RC4_AllocateContext,
|
||||
|
||||
MD2_Clone,
|
||||
MD5_Clone,
|
||||
SHA1_Clone,
|
||||
SHA256_Clone,
|
||||
SHA384_Clone,
|
||||
SHA512_Clone,
|
||||
|
||||
TLS_PRF,
|
||||
HASH_GetRawHashObject,
|
||||
|
||||
HMAC_Create,
|
||||
HMAC_Init,
|
||||
HMAC_Begin,
|
||||
HMAC_Update,
|
||||
HMAC_Clone,
|
||||
HMAC_Finish,
|
||||
HMAC_Destroy,
|
||||
|
||||
RNG_SystemInfoForRNG,
|
||||
|
||||
/* End of Version 3.008. */
|
||||
|
||||
FIPS186Change_GenerateX,
|
||||
FIPS186Change_ReduceModQForDSA,
|
||||
|
||||
/* End of Version 3.009. */
|
||||
Camellia_InitContext,
|
||||
Camellia_AllocateContext,
|
||||
Camellia_CreateContext,
|
||||
Camellia_DestroyContext,
|
||||
Camellia_Encrypt,
|
||||
Camellia_Decrypt,
|
||||
|
||||
/* End of Version 3.010. */
|
||||
PQG_DestroyParams,
|
||||
PQG_DestroyVerify,
|
||||
|
||||
};
|
||||
|
||||
const FREEBLVector *
|
||||
FREEBL_GetVector(void)
|
||||
{
|
||||
extern const char __nss_freebl_rcsid[];
|
||||
extern const char __nss_freebl_sccsid[];
|
||||
|
||||
/* force a reference that won't get optimized away */
|
||||
volatile char c = __nss_freebl_rcsid[0] + __nss_freebl_sccsid[0];
|
||||
|
||||
return &vector;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,506 +0,0 @@
|
||||
/*
|
||||
* loader.h - load platform dependent DSO containing freebl implementation.
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: loader.h,v 1.21 2007-11-13 03:12:48 wtc%google.com Exp $ */
|
||||
|
||||
#ifndef _LOADER_H_
|
||||
#define _LOADER_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define FREEBL_VERSION 0x030A
|
||||
|
||||
struct FREEBLVectorStr {
|
||||
|
||||
unsigned short length; /* of this struct in bytes */
|
||||
unsigned short version; /* of this struct. */
|
||||
|
||||
RSAPrivateKey * (* p_RSA_NewKey)(int keySizeInBits,
|
||||
SECItem * publicExponent);
|
||||
|
||||
SECStatus (* p_RSA_PublicKeyOp) (RSAPublicKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOp)(RSAPrivateKey * key,
|
||||
unsigned char * output,
|
||||
const unsigned char * input);
|
||||
|
||||
SECStatus (* p_DSA_NewKey)(const PQGParams * params,
|
||||
DSAPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigest)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_VerifyDigest)(DSAPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_DSA_NewKeyFromSeed)(const PQGParams *params,
|
||||
const unsigned char * seed,
|
||||
DSAPrivateKey **privKey);
|
||||
|
||||
SECStatus (* p_DSA_SignDigestWithSeed)(DSAPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed);
|
||||
|
||||
SECStatus (* p_DH_GenParam)(int primeLen, DHParams ** params);
|
||||
|
||||
SECStatus (* p_DH_NewKey)(DHParams * params,
|
||||
DHPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_DH_Derive)(SECItem * publicValue,
|
||||
SECItem * prime,
|
||||
SECItem * privateValue,
|
||||
SECItem * derivedSecret,
|
||||
unsigned int maxOutBytes);
|
||||
|
||||
SECStatus (* p_KEA_Derive)(SECItem *prime,
|
||||
SECItem *public1,
|
||||
SECItem *public2,
|
||||
SECItem *private1,
|
||||
SECItem *private2,
|
||||
SECItem *derivedSecret);
|
||||
|
||||
PRBool (* p_KEA_Verify)(SECItem *Y, SECItem *prime, SECItem *subPrime);
|
||||
|
||||
RC4Context * (* p_RC4_CreateContext)(const unsigned char *key, int len);
|
||||
|
||||
void (* p_RC4_DestroyContext)(RC4Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC4_Encrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC4_Decrypt)(RC4Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC2Context * (* p_RC2_CreateContext)(const unsigned char *key,
|
||||
unsigned int len, const unsigned char *iv,
|
||||
int mode, unsigned effectiveKeyLen);
|
||||
|
||||
void (* p_RC2_DestroyContext)(RC2Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC2_Encrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC2_Decrypt)(RC2Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
RC5Context *(* p_RC5_CreateContext)(const SECItem *key, unsigned int rounds,
|
||||
unsigned int wordSize, const unsigned char *iv, int mode);
|
||||
|
||||
void (* p_RC5_DestroyContext)(RC5Context *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_RC5_Encrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_RC5_Decrypt)(RC5Context *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
DESContext *(* p_DES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, PRBool encrypt);
|
||||
|
||||
void (* p_DES_DestroyContext)(DESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_DES_Encrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_DES_Decrypt)(DESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
AESContext * (* p_AES_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, int encrypt, unsigned int keylen,
|
||||
unsigned int blocklen);
|
||||
|
||||
void (* p_AES_DestroyContext)(AESContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AES_Encrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AES_Decrypt)(AESContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_MD5_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_MD5_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
MD5Context *(* p_MD5_NewContext)(void);
|
||||
|
||||
void (* p_MD5_DestroyContext)(MD5Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD5_Begin)(MD5Context *cx);
|
||||
|
||||
void (* p_MD5_Update)(MD5Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD5_End)(MD5Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD5_FlattenSize)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD5_Flatten)(MD5Context *cx,unsigned char *space);
|
||||
|
||||
MD5Context * (* p_MD5_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
void (* p_MD5_TraceState)(MD5Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
MD2Context *(* p_MD2_NewContext)(void);
|
||||
|
||||
void (* p_MD2_DestroyContext)(MD2Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_MD2_Begin)(MD2Context *cx);
|
||||
|
||||
void (* p_MD2_Update)(MD2Context *cx,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
void (* p_MD2_End)(MD2Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
unsigned int (* p_MD2_FlattenSize)(MD2Context *cx);
|
||||
|
||||
SECStatus (* p_MD2_Flatten)(MD2Context *cx,unsigned char *space);
|
||||
|
||||
MD2Context * (* p_MD2_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_SHA1_Hash)(unsigned char *dest, const char *src);
|
||||
|
||||
SECStatus (* p_SHA1_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
|
||||
SHA1Context *(* p_SHA1_NewContext)(void);
|
||||
|
||||
void (* p_SHA1_DestroyContext)(SHA1Context *cx, PRBool freeit);
|
||||
|
||||
void (* p_SHA1_Begin)(SHA1Context *cx);
|
||||
|
||||
void (* p_SHA1_Update)(SHA1Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
void (* p_SHA1_End)(SHA1Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
|
||||
void (* p_SHA1_TraceState)(SHA1Context *cx);
|
||||
|
||||
unsigned int (* p_SHA1_FlattenSize)(SHA1Context *cx);
|
||||
|
||||
SECStatus (* p_SHA1_Flatten)(SHA1Context *cx,unsigned char *space);
|
||||
|
||||
SHA1Context * (* p_SHA1_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SECStatus (* p_RNG_RNGInit)(void);
|
||||
|
||||
SECStatus (* p_RNG_RandomUpdate)(const void *data, size_t bytes);
|
||||
|
||||
SECStatus (* p_RNG_GenerateGlobalRandomBytes)(void *dest, size_t len);
|
||||
|
||||
void (* p_RNG_RNGShutdown)(void);
|
||||
|
||||
SECStatus (* p_PQG_ParamGen)(unsigned int j, PQGParams **pParams,
|
||||
PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_ParamGenSeedLen)( unsigned int j, unsigned int seedBytes,
|
||||
PQGParams **pParams, PQGVerify **pVfy);
|
||||
|
||||
SECStatus (* p_PQG_VerifyParams)(const PQGParams *params,
|
||||
const PQGVerify *vfy, SECStatus *result);
|
||||
|
||||
/* Version 3.001 came to here */
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyOpDoubleChecked)(RSAPrivateKey *key,
|
||||
unsigned char *output,
|
||||
const unsigned char *input);
|
||||
|
||||
SECStatus (* p_RSA_PrivateKeyCheck)(RSAPrivateKey *key);
|
||||
|
||||
void (* p_BL_Cleanup)(void);
|
||||
|
||||
/* Version 3.002 came to here */
|
||||
|
||||
SHA256Context *(* p_SHA256_NewContext)(void);
|
||||
void (* p_SHA256_DestroyContext)(SHA256Context *cx, PRBool freeit);
|
||||
void (* p_SHA256_Begin)(SHA256Context *cx);
|
||||
void (* p_SHA256_Update)(SHA256Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA256_End)(SHA256Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA256_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA256_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA256_TraceState)(SHA256Context *cx);
|
||||
unsigned int (* p_SHA256_FlattenSize)(SHA256Context *cx);
|
||||
SECStatus (* p_SHA256_Flatten)(SHA256Context *cx,unsigned char *space);
|
||||
SHA256Context * (* p_SHA256_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA512Context *(* p_SHA512_NewContext)(void);
|
||||
void (* p_SHA512_DestroyContext)(SHA512Context *cx, PRBool freeit);
|
||||
void (* p_SHA512_Begin)(SHA512Context *cx);
|
||||
void (* p_SHA512_Update)(SHA512Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA512_End)(SHA512Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA512_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA512_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA512_TraceState)(SHA512Context *cx);
|
||||
unsigned int (* p_SHA512_FlattenSize)(SHA512Context *cx);
|
||||
SECStatus (* p_SHA512_Flatten)(SHA512Context *cx,unsigned char *space);
|
||||
SHA512Context * (* p_SHA512_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
SHA384Context *(* p_SHA384_NewContext)(void);
|
||||
void (* p_SHA384_DestroyContext)(SHA384Context *cx, PRBool freeit);
|
||||
void (* p_SHA384_Begin)(SHA384Context *cx);
|
||||
void (* p_SHA384_Update)(SHA384Context *cx, const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
void (* p_SHA384_End)(SHA384Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen);
|
||||
SECStatus (* p_SHA384_HashBuf)(unsigned char *dest, const unsigned char *src,
|
||||
uint32 src_length);
|
||||
SECStatus (* p_SHA384_Hash)(unsigned char *dest, const char *src);
|
||||
void (* p_SHA384_TraceState)(SHA384Context *cx);
|
||||
unsigned int (* p_SHA384_FlattenSize)(SHA384Context *cx);
|
||||
SECStatus (* p_SHA384_Flatten)(SHA384Context *cx,unsigned char *space);
|
||||
SHA384Context * (* p_SHA384_Resurrect)(unsigned char *space, void *arg);
|
||||
|
||||
/* Version 3.003 came to here */
|
||||
|
||||
AESKeyWrapContext * (* p_AESKeyWrap_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv, int encrypt, unsigned int keylen);
|
||||
|
||||
void (* p_AESKeyWrap_DestroyContext)(AESKeyWrapContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Encrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_AESKeyWrap_Decrypt)(AESKeyWrapContext *cx,
|
||||
unsigned char *output,
|
||||
unsigned int *outputLen, unsigned int maxOutputLen,
|
||||
const unsigned char *input, unsigned int inputLen);
|
||||
|
||||
/* Version 3.004 came to here */
|
||||
|
||||
PRBool (*p_BLAPI_SHVerify)(const char *name, PRFuncPtr addr);
|
||||
PRBool (*p_BLAPI_VerifySelf)(const char *name);
|
||||
|
||||
/* Version 3.005 came to here */
|
||||
|
||||
SECStatus (* p_EC_NewKey)(ECParams * params,
|
||||
ECPrivateKey ** privKey);
|
||||
|
||||
SECStatus (* p_EC_NewKeyFromSeed)(ECParams * params,
|
||||
ECPrivateKey ** privKey,
|
||||
const unsigned char * seed,
|
||||
int seedlen);
|
||||
|
||||
SECStatus (* p_EC_ValidatePublicKey)(ECParams * params,
|
||||
SECItem * publicValue);
|
||||
|
||||
SECStatus (* p_ECDH_Derive)(SECItem * publicValue,
|
||||
ECParams * params,
|
||||
SECItem * privateValue,
|
||||
PRBool withCofactor,
|
||||
SECItem * derivedSecret);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigest)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_VerifyDigest)(ECPublicKey * key,
|
||||
const SECItem * signature,
|
||||
const SECItem * digest);
|
||||
|
||||
SECStatus (* p_ECDSA_SignDigestWithSeed)(ECPrivateKey * key,
|
||||
SECItem * signature,
|
||||
const SECItem * digest,
|
||||
const unsigned char * seed,
|
||||
const int seedlen);
|
||||
|
||||
/* Version 3.006 came to here */
|
||||
|
||||
/* no modification to FREEBLVectorStr itself
|
||||
* but ECParamStr was modified
|
||||
*/
|
||||
|
||||
/* Version 3.007 came to here */
|
||||
|
||||
SECStatus (* p_AES_InitContext)(AESContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int mode,
|
||||
unsigned int encrypt,
|
||||
unsigned int blocklen);
|
||||
SECStatus (* p_AESKeyWrap_InitContext)(AESKeyWrapContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int mode,
|
||||
unsigned int encrypt,
|
||||
unsigned int blocklen);
|
||||
SECStatus (* p_DES_InitContext)(DESContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int mode,
|
||||
unsigned int encrypt,
|
||||
unsigned int );
|
||||
SECStatus (* p_RC2_InitContext)(RC2Context *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int mode,
|
||||
unsigned int effectiveKeyLen,
|
||||
unsigned int );
|
||||
SECStatus (* p_RC4_InitContext)(RC4Context *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *,
|
||||
int,
|
||||
unsigned int ,
|
||||
unsigned int );
|
||||
|
||||
AESContext *(*p_AES_AllocateContext)(void);
|
||||
AESKeyWrapContext *(*p_AESKeyWrap_AllocateContext)(void);
|
||||
DESContext *(*p_DES_AllocateContext)(void);
|
||||
RC2Context *(*p_RC2_AllocateContext)(void);
|
||||
RC4Context *(*p_RC4_AllocateContext)(void);
|
||||
|
||||
void (* p_MD2_Clone)(MD2Context *dest, MD2Context *src);
|
||||
void (* p_MD5_Clone)(MD5Context *dest, MD5Context *src);
|
||||
void (* p_SHA1_Clone)(SHA1Context *dest, SHA1Context *src);
|
||||
void (* p_SHA256_Clone)(SHA256Context *dest, SHA256Context *src);
|
||||
void (* p_SHA384_Clone)(SHA384Context *dest, SHA384Context *src);
|
||||
void (* p_SHA512_Clone)(SHA512Context *dest, SHA512Context *src);
|
||||
|
||||
SECStatus (* p_TLS_PRF)(const SECItem *secret, const char *label,
|
||||
SECItem *seed, SECItem *result, PRBool isFIPS);
|
||||
|
||||
const SECHashObject *(* p_HASH_GetRawHashObject)(HASH_HashType hashType);
|
||||
|
||||
HMACContext * (* p_HMAC_Create)(const SECHashObject *hashObj,
|
||||
const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS);
|
||||
SECStatus (* p_HMAC_Init)(HMACContext *cx, const SECHashObject *hash_obj,
|
||||
const unsigned char *secret,
|
||||
unsigned int secret_len, PRBool isFIPS);
|
||||
void (* p_HMAC_Begin)(HMACContext *cx);
|
||||
void (* p_HMAC_Update)(HMACContext *cx, const unsigned char *data,
|
||||
unsigned int data_len);
|
||||
HMACContext * (* p_HMAC_Clone)(HMACContext *cx);
|
||||
SECStatus (* p_HMAC_Finish)(HMACContext *cx, unsigned char *result,
|
||||
unsigned int *result_len,
|
||||
unsigned int max_result_len);
|
||||
void (* p_HMAC_Destroy)(HMACContext *cx, PRBool freeit);
|
||||
|
||||
void (* p_RNG_SystemInfoForRNG)(void);
|
||||
|
||||
/* Version 3.008 came to here */
|
||||
|
||||
SECStatus (* p_FIPS186Change_GenerateX)(unsigned char *XKEY,
|
||||
const unsigned char *XSEEDj,
|
||||
unsigned char *x_j);
|
||||
SECStatus (* p_FIPS186Change_ReduceModQForDSA)(const unsigned char *w,
|
||||
const unsigned char *q,
|
||||
unsigned char *xj);
|
||||
|
||||
/* Version 3.009 came to here */
|
||||
|
||||
SECStatus (* p_Camellia_InitContext)(CamelliaContext *cx,
|
||||
const unsigned char *key,
|
||||
unsigned int keylen,
|
||||
const unsigned char *iv,
|
||||
int mode,
|
||||
unsigned int encrypt,
|
||||
unsigned int unused);
|
||||
|
||||
CamelliaContext *(*p_Camellia_AllocateContext)(void);
|
||||
CamelliaContext * (* p_Camellia_CreateContext)(const unsigned char *key,
|
||||
const unsigned char *iv,
|
||||
int mode, int encrypt,
|
||||
unsigned int keylen);
|
||||
void (* p_Camellia_DestroyContext)(CamelliaContext *cx, PRBool freeit);
|
||||
|
||||
SECStatus (* p_Camellia_Encrypt)(CamelliaContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
SECStatus (* p_Camellia_Decrypt)(CamelliaContext *cx, unsigned char *output,
|
||||
unsigned int *outputLen,
|
||||
unsigned int maxOutputLen,
|
||||
const unsigned char *input,
|
||||
unsigned int inputLen);
|
||||
|
||||
void (* p_PQG_DestroyParams)(PQGParams *params);
|
||||
|
||||
void (* p_PQG_DestroyVerify)(PQGVerify *vfy);
|
||||
|
||||
/* Version 3.010 came to here */
|
||||
};
|
||||
|
||||
typedef struct FREEBLVectorStr FREEBLVector;
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
typedef const FREEBLVector * FREEBLGetVectorFn(void);
|
||||
|
||||
extern FREEBLGetVectorFn FREEBL_GetVector;
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
@@ -1,318 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef notdef
|
||||
#include "xp_core.h"
|
||||
#include "xp_file.h"
|
||||
#endif
|
||||
#include "secrng.h"
|
||||
#include "mcom_db.h"
|
||||
#ifdef XP_MAC
|
||||
#include <Events.h>
|
||||
#include <OSUtils.h>
|
||||
#include <QDOffscreen.h>
|
||||
#include <PPCToolbox.h>
|
||||
#include <Processes.h>
|
||||
#include <LowMem.h>
|
||||
#include <Scrap.h>
|
||||
|
||||
/* Static prototypes */
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen);
|
||||
void FE_ReadScreen();
|
||||
|
||||
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
|
||||
{
|
||||
union endianness {
|
||||
int32 i;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
if (srclen <= dstlen) {
|
||||
memcpy(dst, src, srclen);
|
||||
return srclen;
|
||||
}
|
||||
u.i = 0x01020304;
|
||||
if (u.c[0] == 0x01) {
|
||||
/* big-endian case */
|
||||
memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
|
||||
} else {
|
||||
/* little-endian case */
|
||||
memcpy(dst, src, dstlen);
|
||||
}
|
||||
return dstlen;
|
||||
}
|
||||
|
||||
size_t RNG_GetNoise(void *buf, size_t maxbytes)
|
||||
{
|
||||
UnsignedWide microTickCount;
|
||||
Microseconds(µTickCount);
|
||||
return CopyLowBits(buf, maxbytes, µTickCount, sizeof(microTickCount));
|
||||
}
|
||||
|
||||
void RNG_FileForRNG(const char *filename)
|
||||
{
|
||||
unsigned char buffer[BUFSIZ];
|
||||
size_t bytes;
|
||||
#ifdef notdef /*sigh*/
|
||||
XP_File file;
|
||||
unsigned long totalFileBytes = 0;
|
||||
|
||||
if (filename == NULL) /* For now, read in global history if filename is null */
|
||||
file = XP_FileOpen(NULL, xpGlobalHistory,XP_FILE_READ_BIN);
|
||||
else
|
||||
file = XP_FileOpen(NULL, xpURL,XP_FILE_READ_BIN);
|
||||
if (file != NULL) {
|
||||
for (;;) {
|
||||
bytes = XP_FileRead(buffer, sizeof(buffer), file);
|
||||
if (bytes == 0) break;
|
||||
RNG_RandomUpdate( buffer, bytes);
|
||||
totalFileBytes += bytes;
|
||||
if (totalFileBytes > 100*1024) break; /* No more than 100 K */
|
||||
}
|
||||
XP_FileClose(file);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Pass yet another snapshot of our highest resolution clock into
|
||||
* the hash function.
|
||||
*/
|
||||
bytes = RNG_GetNoise(buffer, sizeof(buffer));
|
||||
RNG_RandomUpdate(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void RNG_SystemInfoForRNG()
|
||||
{
|
||||
/* Time */
|
||||
{
|
||||
unsigned long sec;
|
||||
size_t bytes;
|
||||
GetDateTime(&sec); /* Current time since 1970 */
|
||||
RNG_RandomUpdate( &sec, sizeof(sec));
|
||||
bytes = RNG_GetNoise(&sec, sizeof(sec));
|
||||
RNG_RandomUpdate(&sec, bytes);
|
||||
}
|
||||
/* User specific variables */
|
||||
{
|
||||
MachineLocation loc;
|
||||
ReadLocation(&loc);
|
||||
RNG_RandomUpdate( &loc, sizeof(loc));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* User name */
|
||||
{
|
||||
unsigned long userRef;
|
||||
Str32 userName;
|
||||
GetDefaultUser(&userRef, userName);
|
||||
RNG_RandomUpdate( &userRef, sizeof(userRef));
|
||||
RNG_RandomUpdate( userName, sizeof(userName));
|
||||
}
|
||||
#endif
|
||||
/* Mouse location */
|
||||
{
|
||||
Point mouseLoc;
|
||||
GetMouse(&mouseLoc);
|
||||
RNG_RandomUpdate( &mouseLoc, sizeof(mouseLoc));
|
||||
}
|
||||
/* Keyboard time threshold */
|
||||
{
|
||||
SInt16 keyTresh = LMGetKeyThresh();
|
||||
RNG_RandomUpdate( &keyTresh, sizeof(keyTresh));
|
||||
}
|
||||
/* Last key pressed */
|
||||
{
|
||||
SInt8 keyLast;
|
||||
keyLast = LMGetKbdLast();
|
||||
RNG_RandomUpdate( &keyLast, sizeof(keyLast));
|
||||
}
|
||||
/* Volume */
|
||||
{
|
||||
UInt8 volume = LMGetSdVolume();
|
||||
RNG_RandomUpdate( &volume, sizeof(volume));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Current directory */
|
||||
{
|
||||
SInt32 dir = LMGetCurDirStore();
|
||||
RNG_RandomUpdate( &dir, sizeof(dir));
|
||||
}
|
||||
#endif
|
||||
/* Process information about all the processes in the machine */
|
||||
{
|
||||
ProcessSerialNumber process;
|
||||
ProcessInfoRec pi;
|
||||
|
||||
process.highLongOfPSN = process.lowLongOfPSN = kNoProcess;
|
||||
|
||||
while (GetNextProcess(&process) == noErr)
|
||||
{
|
||||
FSSpec fileSpec;
|
||||
pi.processInfoLength = sizeof(ProcessInfoRec);
|
||||
pi.processName = NULL;
|
||||
pi.processAppSpec = &fileSpec;
|
||||
GetProcessInformation(&process, &pi);
|
||||
RNG_RandomUpdate( &pi, sizeof(pi));
|
||||
RNG_RandomUpdate( &fileSpec, sizeof(fileSpec));
|
||||
}
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Heap */
|
||||
{
|
||||
THz zone = LMGetTheZone();
|
||||
RNG_RandomUpdate( &zone, sizeof(zone));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Screen */
|
||||
{
|
||||
GDHandle h = GetMainDevice(); /* GDHandle is **GDevice */
|
||||
RNG_RandomUpdate( *h, sizeof(GDevice));
|
||||
}
|
||||
|
||||
#if !TARGET_CARBON
|
||||
/* Scrap size */
|
||||
{
|
||||
SInt32 scrapSize = LMGetScrapSize();
|
||||
RNG_RandomUpdate( &scrapSize, sizeof(scrapSize));
|
||||
}
|
||||
/* Scrap count */
|
||||
{
|
||||
SInt16 scrapCount = LMGetScrapCount();
|
||||
RNG_RandomUpdate( &scrapCount, sizeof(scrapCount));
|
||||
}
|
||||
#else
|
||||
{
|
||||
ScrapRef scrap;
|
||||
if (GetCurrentScrap(&scrap) == noErr) {
|
||||
UInt32 flavorCount;
|
||||
if (GetScrapFlavorCount(scrap, &flavorCount) == noErr) {
|
||||
ScrapFlavorInfo* flavorInfo = (ScrapFlavorInfo*) malloc(flavorCount * sizeof(ScrapFlavorInfo));
|
||||
if (flavorInfo != NULL) {
|
||||
if (GetScrapFlavorInfoList(scrap, &flavorCount, flavorInfo) == noErr) {
|
||||
UInt32 i;
|
||||
RNG_RandomUpdate(&flavorCount, sizeof(flavorCount));
|
||||
for (i = 0; i < flavorCount; ++i) {
|
||||
Size flavorSize;
|
||||
if (GetScrapFlavorSize(scrap, flavorInfo[i].flavorType, &flavorSize) == noErr)
|
||||
RNG_RandomUpdate(&flavorSize, sizeof(flavorSize));
|
||||
}
|
||||
}
|
||||
free(flavorInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* File stuff, last modified, etc. */
|
||||
{
|
||||
HParamBlockRec pb;
|
||||
GetVolParmsInfoBuffer volInfo;
|
||||
pb.ioParam.ioVRefNum = 0;
|
||||
pb.ioParam.ioNamePtr = nil;
|
||||
pb.ioParam.ioBuffer = (Ptr) &volInfo;
|
||||
pb.ioParam.ioReqCount = sizeof(volInfo);
|
||||
PBHGetVolParmsSync(&pb);
|
||||
RNG_RandomUpdate( &volInfo, sizeof(volInfo));
|
||||
}
|
||||
#if !TARGET_CARBON
|
||||
/* Event queue */
|
||||
{
|
||||
EvQElPtr eventQ;
|
||||
for (eventQ = (EvQElPtr) LMGetEventQueue()->qHead;
|
||||
eventQ;
|
||||
eventQ = (EvQElPtr)eventQ->qLink)
|
||||
RNG_RandomUpdate( &eventQ->evtQWhat, sizeof(EventRecord));
|
||||
}
|
||||
#endif
|
||||
FE_ReadScreen();
|
||||
RNG_FileForRNG(NULL);
|
||||
}
|
||||
|
||||
void FE_ReadScreen()
|
||||
{
|
||||
UInt16 coords[4];
|
||||
PixMapHandle pmap;
|
||||
GDHandle gh;
|
||||
UInt16 screenHeight;
|
||||
UInt16 screenWidth; /* just what they say */
|
||||
UInt32 bytesToRead; /* number of bytes we're giving */
|
||||
UInt32 offset; /* offset into the graphics buffer */
|
||||
UInt16 rowBytes;
|
||||
UInt32 rowsToRead;
|
||||
float bytesPerPixel; /* dependent on buffer depth */
|
||||
Ptr p; /* temporary */
|
||||
UInt16 x, y, w, h;
|
||||
|
||||
gh = LMGetMainDevice();
|
||||
if ( !gh )
|
||||
return;
|
||||
pmap = (**gh).gdPMap;
|
||||
if ( !pmap )
|
||||
return;
|
||||
|
||||
RNG_GenerateGlobalRandomBytes( coords, sizeof( coords ) );
|
||||
|
||||
/* make x and y inside the screen rect */
|
||||
screenHeight = (**pmap).bounds.bottom - (**pmap).bounds.top;
|
||||
screenWidth = (**pmap).bounds.right - (**pmap).bounds.left;
|
||||
x = coords[0] % screenWidth;
|
||||
y = coords[1] % screenHeight;
|
||||
w = ( coords[2] & 0x7F ) | 0x40; /* Make sure that w is in the range 64..128 */
|
||||
h = ( coords[3] & 0x7F ) | 0x40; /* same for h */
|
||||
|
||||
bytesPerPixel = (**pmap).pixelSize / 8;
|
||||
rowBytes = (**pmap).rowBytes & 0x7FFF;
|
||||
|
||||
/* starting address */
|
||||
offset = ( rowBytes * y ) + (UInt32)( (float)x * bytesPerPixel );
|
||||
|
||||
/* don't read past the end of the pixmap's rowbytes */
|
||||
bytesToRead = PR_MIN( (UInt32)( w * bytesPerPixel ),
|
||||
(UInt32)( rowBytes - ( x * bytesPerPixel ) ) );
|
||||
|
||||
/* don't read past the end of the graphics device pixmap */
|
||||
rowsToRead = PR_MIN( h,
|
||||
( screenHeight - y ) );
|
||||
|
||||
p = GetPixBaseAddr( pmap ) + offset;
|
||||
|
||||
while ( rowsToRead-- )
|
||||
{
|
||||
RNG_RandomUpdate( p, bytesToRead );
|
||||
p += rowBytes;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,186 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Dr Vipul Gupta <vipul.gupta@sun.com> and
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# NOTE: any ifdefs in this file must be defined on the gmake command line
|
||||
# (if anywhere). They cannot come from Makefile or config.mk
|
||||
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
LIBRARY_NAME = freebl
|
||||
LIBRARY_VERSION = 3
|
||||
|
||||
ifdef FREEBL_CHILD_BUILD
|
||||
ifdef USE_ABI32_INT32
|
||||
LIBRARY_NAME = freebl_32int
|
||||
endif
|
||||
ifdef USE_ABI32_INT64
|
||||
LIBRARY_NAME = freebl_32int64
|
||||
endif
|
||||
ifdef USE_ABI32_FPU
|
||||
LIBRARY_NAME = freebl_32fpu
|
||||
endif
|
||||
ifdef USE_ABI64_INT
|
||||
LIBRARY_NAME = freebl_64int
|
||||
endif
|
||||
ifdef USE_ABI64_FPU
|
||||
LIBRARY_NAME = freebl_64fpu
|
||||
endif
|
||||
endif
|
||||
|
||||
# if the library name contains _, we prefix the version with _
|
||||
ifneq (,$(findstring _,$(LIBRARY_NAME)))
|
||||
LIBRARY_VERSION := _$(LIBRARY_VERSION)
|
||||
endif
|
||||
|
||||
MAPFILE_SOURCE = freebl.def
|
||||
MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def
|
||||
|
||||
SOFTOKEN_LIBRARY_VERSION = 3
|
||||
|
||||
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
|
||||
-DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" \
|
||||
-DSOFTOKEN_SHLIB_VERSION=\"$(SOFTOKEN_LIBRARY_VERSION)\"
|
||||
|
||||
REQUIRES =
|
||||
|
||||
EXPORTS = \
|
||||
blapit.h \
|
||||
shsign.h \
|
||||
ecl-exp.h \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
alghmac.h \
|
||||
blapi.h \
|
||||
secmpi.h \
|
||||
secrng.h \
|
||||
ec.h \
|
||||
ecl.h \
|
||||
ecl-curve.h \
|
||||
$(NULL)
|
||||
|
||||
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
|
||||
MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
|
||||
|
||||
|
||||
ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h
|
||||
ifdef NSS_ENABLE_ECC
|
||||
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
|
||||
ecp_aff.c ecp_jac.c ecp_mont.c \
|
||||
ec_naf.c ecp_jm.c
|
||||
ifdef NSS_ECC_MORE_THAN_SUITE_B
|
||||
ECL_SRCS += ec2_aff.c ec2_mont.c ec2_proj.c \
|
||||
ec2_163.c ec2_193.c ec2_233.c \
|
||||
ecp_192.c ecp_224.c ecp_256.c ecp_384.c ecp_521.c
|
||||
endif
|
||||
else
|
||||
ECL_SRCS = $(NULL)
|
||||
endif
|
||||
SHA_SRCS = sha_fast.c
|
||||
MPCPU_SRCS = mpcpucache.c
|
||||
|
||||
CSRCS = \
|
||||
freeblver.c \
|
||||
ldvector.c \
|
||||
prng_fips1861.c \
|
||||
sysrand.c \
|
||||
$(SHA_SRCS) \
|
||||
md2.c \
|
||||
md5.c \
|
||||
sha512.c \
|
||||
alghmac.c \
|
||||
rawhash.c \
|
||||
alg2268.c \
|
||||
arcfour.c \
|
||||
arcfive.c \
|
||||
desblapi.c \
|
||||
des.c \
|
||||
rijndael.c \
|
||||
aeskeywrap.c \
|
||||
camellia.c \
|
||||
dh.c \
|
||||
ec.c \
|
||||
pqg.c \
|
||||
dsa.c \
|
||||
rsa.c \
|
||||
shvfy.c \
|
||||
tlsprfalg.c \
|
||||
$(MPI_SRCS) \
|
||||
$(MPCPU_SRCS) \
|
||||
$(ECL_SRCS) \
|
||||
$(NULL)
|
||||
|
||||
ALL_CSRCS := $(CSRCS)
|
||||
|
||||
ALL_HDRS = \
|
||||
alghmac.h \
|
||||
blapi.h \
|
||||
blapit.h \
|
||||
des.h \
|
||||
ec.h \
|
||||
loader.h \
|
||||
rijndael.h \
|
||||
camellia.h \
|
||||
secmpi.h \
|
||||
sha_fast.h \
|
||||
sha256.h \
|
||||
shsign.h \
|
||||
vis_proto.h \
|
||||
$(NULL)
|
||||
|
||||
|
||||
ifdef AES_GEN_TBL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES
|
||||
else
|
||||
ifdef AES_GEN_TBL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_TABLES_MACRO
|
||||
else
|
||||
ifdef AES_GEN_VAL
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES
|
||||
else
|
||||
ifdef AES_GEN_VAL_M
|
||||
DEFINES += -DRIJNDAEL_GENERATE_VALUES_MACRO
|
||||
else
|
||||
DEFINES += -DRIJNDAEL_INCLUDE_TABLES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -1,43 +0,0 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
libfreebl_3.so {
|
||||
global:
|
||||
FREEBL_GetVector;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
@@ -1,296 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define MD2_DIGEST_LEN 16
|
||||
#define MD2_BUFSIZE 16
|
||||
#define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */
|
||||
#define MD2_CV 0 /* index into X for chaining variables */
|
||||
#define MD2_INPUT 16 /* index into X for input */
|
||||
#define MD2_TMPVARS 32 /* index into X for temporary variables */
|
||||
#define MD2_CHECKSUM_SIZE 16
|
||||
|
||||
struct MD2ContextStr {
|
||||
unsigned char checksum[MD2_BUFSIZE];
|
||||
unsigned char X[MD2_X_SIZE];
|
||||
PRUint8 unusedBuffer;
|
||||
};
|
||||
|
||||
static const PRUint8 MD2S[256] = {
|
||||
0051, 0056, 0103, 0311, 0242, 0330, 0174, 0001,
|
||||
0075, 0066, 0124, 0241, 0354, 0360, 0006, 0023,
|
||||
0142, 0247, 0005, 0363, 0300, 0307, 0163, 0214,
|
||||
0230, 0223, 0053, 0331, 0274, 0114, 0202, 0312,
|
||||
0036, 0233, 0127, 0074, 0375, 0324, 0340, 0026,
|
||||
0147, 0102, 0157, 0030, 0212, 0027, 0345, 0022,
|
||||
0276, 0116, 0304, 0326, 0332, 0236, 0336, 0111,
|
||||
0240, 0373, 0365, 0216, 0273, 0057, 0356, 0172,
|
||||
0251, 0150, 0171, 0221, 0025, 0262, 0007, 0077,
|
||||
0224, 0302, 0020, 0211, 0013, 0042, 0137, 0041,
|
||||
0200, 0177, 0135, 0232, 0132, 0220, 0062, 0047,
|
||||
0065, 0076, 0314, 0347, 0277, 0367, 0227, 0003,
|
||||
0377, 0031, 0060, 0263, 0110, 0245, 0265, 0321,
|
||||
0327, 0136, 0222, 0052, 0254, 0126, 0252, 0306,
|
||||
0117, 0270, 0070, 0322, 0226, 0244, 0175, 0266,
|
||||
0166, 0374, 0153, 0342, 0234, 0164, 0004, 0361,
|
||||
0105, 0235, 0160, 0131, 0144, 0161, 0207, 0040,
|
||||
0206, 0133, 0317, 0145, 0346, 0055, 0250, 0002,
|
||||
0033, 0140, 0045, 0255, 0256, 0260, 0271, 0366,
|
||||
0034, 0106, 0141, 0151, 0064, 0100, 0176, 0017,
|
||||
0125, 0107, 0243, 0043, 0335, 0121, 0257, 0072,
|
||||
0303, 0134, 0371, 0316, 0272, 0305, 0352, 0046,
|
||||
0054, 0123, 0015, 0156, 0205, 0050, 0204, 0011,
|
||||
0323, 0337, 0315, 0364, 0101, 0201, 0115, 0122,
|
||||
0152, 0334, 0067, 0310, 0154, 0301, 0253, 0372,
|
||||
0044, 0341, 0173, 0010, 0014, 0275, 0261, 0112,
|
||||
0170, 0210, 0225, 0213, 0343, 0143, 0350, 0155,
|
||||
0351, 0313, 0325, 0376, 0073, 0000, 0035, 0071,
|
||||
0362, 0357, 0267, 0016, 0146, 0130, 0320, 0344,
|
||||
0246, 0167, 0162, 0370, 0353, 0165, 0113, 0012,
|
||||
0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032,
|
||||
0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024
|
||||
};
|
||||
|
||||
SECStatus
|
||||
MD2_Hash(unsigned char *dest, const char *src)
|
||||
{
|
||||
unsigned int len;
|
||||
MD2Context *cx = MD2_NewContext();
|
||||
if (!cx) {
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return SECFailure;
|
||||
}
|
||||
MD2_Begin(cx);
|
||||
MD2_Update(cx, (unsigned char *)src, PL_strlen(src));
|
||||
MD2_End(cx, dest, &len, MD2_DIGEST_LEN);
|
||||
MD2_DestroyContext(cx, PR_TRUE);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
MD2Context *
|
||||
MD2_NewContext(void)
|
||||
{
|
||||
MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
MD2_DestroyContext(MD2Context *cx, PRBool freeit)
|
||||
{
|
||||
if (freeit)
|
||||
PORT_ZFree(cx, sizeof(*cx));
|
||||
}
|
||||
|
||||
void
|
||||
MD2_Begin(MD2Context *cx)
|
||||
{
|
||||
memset(cx, 0, sizeof(*cx));
|
||||
cx->unusedBuffer = MD2_BUFSIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
md2_compress(MD2Context *cx)
|
||||
{
|
||||
int j;
|
||||
unsigned char P;
|
||||
P = cx->checksum[MD2_CHECKSUM_SIZE-1];
|
||||
/* Compute the running checksum, and set the tmp variables to be
|
||||
* CV[i] XOR input[i]
|
||||
*/
|
||||
#define CKSUMFN(n) \
|
||||
P = cx->checksum[n] ^ MD2S[cx->X[MD2_INPUT+n] ^ P]; \
|
||||
cx->checksum[n] = P; \
|
||||
cx->X[MD2_TMPVARS+n] = cx->X[n] ^ cx->X[MD2_INPUT+n];
|
||||
CKSUMFN(0);
|
||||
CKSUMFN(1);
|
||||
CKSUMFN(2);
|
||||
CKSUMFN(3);
|
||||
CKSUMFN(4);
|
||||
CKSUMFN(5);
|
||||
CKSUMFN(6);
|
||||
CKSUMFN(7);
|
||||
CKSUMFN(8);
|
||||
CKSUMFN(9);
|
||||
CKSUMFN(10);
|
||||
CKSUMFN(11);
|
||||
CKSUMFN(12);
|
||||
CKSUMFN(13);
|
||||
CKSUMFN(14);
|
||||
CKSUMFN(15);
|
||||
/* The compression function. */
|
||||
#define COMPRESS(n) \
|
||||
P = cx->X[n] ^ MD2S[P]; \
|
||||
cx->X[n] = P;
|
||||
P = 0x00;
|
||||
for (j=0; j<18; j++) {
|
||||
COMPRESS(0);
|
||||
COMPRESS(1);
|
||||
COMPRESS(2);
|
||||
COMPRESS(3);
|
||||
COMPRESS(4);
|
||||
COMPRESS(5);
|
||||
COMPRESS(6);
|
||||
COMPRESS(7);
|
||||
COMPRESS(8);
|
||||
COMPRESS(9);
|
||||
COMPRESS(10);
|
||||
COMPRESS(11);
|
||||
COMPRESS(12);
|
||||
COMPRESS(13);
|
||||
COMPRESS(14);
|
||||
COMPRESS(15);
|
||||
COMPRESS(16);
|
||||
COMPRESS(17);
|
||||
COMPRESS(18);
|
||||
COMPRESS(19);
|
||||
COMPRESS(20);
|
||||
COMPRESS(21);
|
||||
COMPRESS(22);
|
||||
COMPRESS(23);
|
||||
COMPRESS(24);
|
||||
COMPRESS(25);
|
||||
COMPRESS(26);
|
||||
COMPRESS(27);
|
||||
COMPRESS(28);
|
||||
COMPRESS(29);
|
||||
COMPRESS(30);
|
||||
COMPRESS(31);
|
||||
COMPRESS(32);
|
||||
COMPRESS(33);
|
||||
COMPRESS(34);
|
||||
COMPRESS(35);
|
||||
COMPRESS(36);
|
||||
COMPRESS(37);
|
||||
COMPRESS(38);
|
||||
COMPRESS(39);
|
||||
COMPRESS(40);
|
||||
COMPRESS(41);
|
||||
COMPRESS(42);
|
||||
COMPRESS(43);
|
||||
COMPRESS(44);
|
||||
COMPRESS(45);
|
||||
COMPRESS(46);
|
||||
COMPRESS(47);
|
||||
P = (P + j) % 256;
|
||||
}
|
||||
cx->unusedBuffer = MD2_BUFSIZE;
|
||||
}
|
||||
|
||||
void
|
||||
MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint32 bytesToConsume;
|
||||
|
||||
/* Fill the remaining input buffer. */
|
||||
if (cx->unusedBuffer != MD2_BUFSIZE) {
|
||||
bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
|
||||
memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],
|
||||
input, bytesToConsume);
|
||||
if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)
|
||||
md2_compress(cx);
|
||||
inputLen -= bytesToConsume;
|
||||
input += bytesToConsume;
|
||||
}
|
||||
|
||||
/* Iterate over 16-byte chunks of the input. */
|
||||
while (inputLen >= MD2_BUFSIZE) {
|
||||
memcpy(&cx->X[MD2_INPUT], input, MD2_BUFSIZE);
|
||||
md2_compress(cx);
|
||||
inputLen -= MD2_BUFSIZE;
|
||||
input += MD2_BUFSIZE;
|
||||
}
|
||||
|
||||
/* Copy any input that remains into the buffer. */
|
||||
if (inputLen)
|
||||
memcpy(&cx->X[MD2_INPUT], input, inputLen);
|
||||
cx->unusedBuffer = MD2_BUFSIZE - inputLen;
|
||||
}
|
||||
|
||||
void
|
||||
MD2_End(MD2Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen)
|
||||
{
|
||||
PRUint8 padStart;
|
||||
if (maxDigestLen < MD2_BUFSIZE) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return;
|
||||
}
|
||||
padStart = MD2_BUFSIZE - cx->unusedBuffer;
|
||||
memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer,
|
||||
cx->unusedBuffer);
|
||||
md2_compress(cx);
|
||||
memcpy(&cx->X[MD2_INPUT], cx->checksum, MD2_BUFSIZE);
|
||||
md2_compress(cx);
|
||||
*digestLen = MD2_DIGEST_LEN;
|
||||
memcpy(digest, &cx->X[MD2_CV], MD2_DIGEST_LEN);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
MD2_FlattenSize(MD2Context *cx)
|
||||
{
|
||||
return sizeof(*cx);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
MD2_Flatten(MD2Context *cx, unsigned char *space)
|
||||
{
|
||||
memcpy(space, cx, sizeof(*cx));
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
MD2Context *
|
||||
MD2_Resurrect(unsigned char *space, void *arg)
|
||||
{
|
||||
MD2Context *cx = MD2_NewContext();
|
||||
if (cx)
|
||||
memcpy(cx, space, sizeof(*cx));
|
||||
return cx;
|
||||
}
|
||||
|
||||
void MD2_Clone(MD2Context *dest, MD2Context *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof *dest);
|
||||
}
|
||||
@@ -1,595 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "prerr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prlong.h"
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define MD5_HASH_LEN 16
|
||||
#define MD5_BUFFER_SIZE 64
|
||||
#define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
|
||||
|
||||
#define CV0_1 0x67452301
|
||||
#define CV0_2 0xefcdab89
|
||||
#define CV0_3 0x98badcfe
|
||||
#define CV0_4 0x10325476
|
||||
|
||||
#define T1_0 0xd76aa478
|
||||
#define T1_1 0xe8c7b756
|
||||
#define T1_2 0x242070db
|
||||
#define T1_3 0xc1bdceee
|
||||
#define T1_4 0xf57c0faf
|
||||
#define T1_5 0x4787c62a
|
||||
#define T1_6 0xa8304613
|
||||
#define T1_7 0xfd469501
|
||||
#define T1_8 0x698098d8
|
||||
#define T1_9 0x8b44f7af
|
||||
#define T1_10 0xffff5bb1
|
||||
#define T1_11 0x895cd7be
|
||||
#define T1_12 0x6b901122
|
||||
#define T1_13 0xfd987193
|
||||
#define T1_14 0xa679438e
|
||||
#define T1_15 0x49b40821
|
||||
|
||||
#define T2_0 0xf61e2562
|
||||
#define T2_1 0xc040b340
|
||||
#define T2_2 0x265e5a51
|
||||
#define T2_3 0xe9b6c7aa
|
||||
#define T2_4 0xd62f105d
|
||||
#define T2_5 0x02441453
|
||||
#define T2_6 0xd8a1e681
|
||||
#define T2_7 0xe7d3fbc8
|
||||
#define T2_8 0x21e1cde6
|
||||
#define T2_9 0xc33707d6
|
||||
#define T2_10 0xf4d50d87
|
||||
#define T2_11 0x455a14ed
|
||||
#define T2_12 0xa9e3e905
|
||||
#define T2_13 0xfcefa3f8
|
||||
#define T2_14 0x676f02d9
|
||||
#define T2_15 0x8d2a4c8a
|
||||
|
||||
#define T3_0 0xfffa3942
|
||||
#define T3_1 0x8771f681
|
||||
#define T3_2 0x6d9d6122
|
||||
#define T3_3 0xfde5380c
|
||||
#define T3_4 0xa4beea44
|
||||
#define T3_5 0x4bdecfa9
|
||||
#define T3_6 0xf6bb4b60
|
||||
#define T3_7 0xbebfbc70
|
||||
#define T3_8 0x289b7ec6
|
||||
#define T3_9 0xeaa127fa
|
||||
#define T3_10 0xd4ef3085
|
||||
#define T3_11 0x04881d05
|
||||
#define T3_12 0xd9d4d039
|
||||
#define T3_13 0xe6db99e5
|
||||
#define T3_14 0x1fa27cf8
|
||||
#define T3_15 0xc4ac5665
|
||||
|
||||
#define T4_0 0xf4292244
|
||||
#define T4_1 0x432aff97
|
||||
#define T4_2 0xab9423a7
|
||||
#define T4_3 0xfc93a039
|
||||
#define T4_4 0x655b59c3
|
||||
#define T4_5 0x8f0ccc92
|
||||
#define T4_6 0xffeff47d
|
||||
#define T4_7 0x85845dd1
|
||||
#define T4_8 0x6fa87e4f
|
||||
#define T4_9 0xfe2ce6e0
|
||||
#define T4_10 0xa3014314
|
||||
#define T4_11 0x4e0811a1
|
||||
#define T4_12 0xf7537e82
|
||||
#define T4_13 0xbd3af235
|
||||
#define T4_14 0x2ad7d2bb
|
||||
#define T4_15 0xeb86d391
|
||||
|
||||
#define R1B0 0
|
||||
#define R1B1 1
|
||||
#define R1B2 2
|
||||
#define R1B3 3
|
||||
#define R1B4 4
|
||||
#define R1B5 5
|
||||
#define R1B6 6
|
||||
#define R1B7 7
|
||||
#define R1B8 8
|
||||
#define R1B9 9
|
||||
#define R1B10 10
|
||||
#define R1B11 11
|
||||
#define R1B12 12
|
||||
#define R1B13 13
|
||||
#define R1B14 14
|
||||
#define R1B15 15
|
||||
|
||||
#define R2B0 1
|
||||
#define R2B1 6
|
||||
#define R2B2 11
|
||||
#define R2B3 0
|
||||
#define R2B4 5
|
||||
#define R2B5 10
|
||||
#define R2B6 15
|
||||
#define R2B7 4
|
||||
#define R2B8 9
|
||||
#define R2B9 14
|
||||
#define R2B10 3
|
||||
#define R2B11 8
|
||||
#define R2B12 13
|
||||
#define R2B13 2
|
||||
#define R2B14 7
|
||||
#define R2B15 12
|
||||
|
||||
#define R3B0 5
|
||||
#define R3B1 8
|
||||
#define R3B2 11
|
||||
#define R3B3 14
|
||||
#define R3B4 1
|
||||
#define R3B5 4
|
||||
#define R3B6 7
|
||||
#define R3B7 10
|
||||
#define R3B8 13
|
||||
#define R3B9 0
|
||||
#define R3B10 3
|
||||
#define R3B11 6
|
||||
#define R3B12 9
|
||||
#define R3B13 12
|
||||
#define R3B14 15
|
||||
#define R3B15 2
|
||||
|
||||
#define R4B0 0
|
||||
#define R4B1 7
|
||||
#define R4B2 14
|
||||
#define R4B3 5
|
||||
#define R4B4 12
|
||||
#define R4B5 3
|
||||
#define R4B6 10
|
||||
#define R4B7 1
|
||||
#define R4B8 8
|
||||
#define R4B9 15
|
||||
#define R4B10 6
|
||||
#define R4B11 13
|
||||
#define R4B12 4
|
||||
#define R4B13 11
|
||||
#define R4B14 2
|
||||
#define R4B15 9
|
||||
|
||||
#define S1_0 7
|
||||
#define S1_1 12
|
||||
#define S1_2 17
|
||||
#define S1_3 22
|
||||
|
||||
#define S2_0 5
|
||||
#define S2_1 9
|
||||
#define S2_2 14
|
||||
#define S2_3 20
|
||||
|
||||
#define S3_0 4
|
||||
#define S3_1 11
|
||||
#define S3_2 16
|
||||
#define S3_3 23
|
||||
|
||||
#define S4_0 6
|
||||
#define S4_1 10
|
||||
#define S4_2 15
|
||||
#define S4_3 21
|
||||
|
||||
struct MD5ContextStr {
|
||||
PRUint32 lsbInput;
|
||||
PRUint32 msbInput;
|
||||
PRUint32 cv[4];
|
||||
union {
|
||||
PRUint8 b[64];
|
||||
PRUint32 w[16];
|
||||
} u;
|
||||
};
|
||||
|
||||
#define inBuf u.b
|
||||
|
||||
SECStatus
|
||||
MD5_Hash(unsigned char *dest, const char *src)
|
||||
{
|
||||
return MD5_HashBuf(dest, (unsigned char *)src, PL_strlen(src));
|
||||
}
|
||||
|
||||
SECStatus
|
||||
MD5_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length)
|
||||
{
|
||||
unsigned int len;
|
||||
MD5Context cx;
|
||||
|
||||
MD5_Begin(&cx);
|
||||
MD5_Update(&cx, src, src_length);
|
||||
MD5_End(&cx, dest, &len, MD5_HASH_LEN);
|
||||
/* memset(&cx, 0, sizeof cx); */
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
MD5Context *
|
||||
MD5_NewContext(void)
|
||||
{
|
||||
/* no need to ZAlloc, MD5_Begin will init the context */
|
||||
MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
|
||||
if (cx == NULL) {
|
||||
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
|
||||
return NULL;
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
void
|
||||
MD5_DestroyContext(MD5Context *cx, PRBool freeit)
|
||||
{
|
||||
/* memset(cx, 0, sizeof *cx); */
|
||||
if (freeit) {
|
||||
PORT_Free(cx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MD5_Begin(MD5Context *cx)
|
||||
{
|
||||
cx->lsbInput = 0;
|
||||
cx->msbInput = 0;
|
||||
/* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */
|
||||
cx->cv[0] = CV0_1;
|
||||
cx->cv[1] = CV0_2;
|
||||
cx->cv[2] = CV0_3;
|
||||
cx->cv[3] = CV0_4;
|
||||
}
|
||||
|
||||
#define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s))
|
||||
|
||||
#if defined(SOLARIS) || defined(HPUX)
|
||||
#define addto64(sumhigh, sumlow, addend) \
|
||||
sumlow += addend; sumhigh += (sumlow < addend);
|
||||
#else
|
||||
#define addto64(sumhigh, sumlow, addend) \
|
||||
sumlow += addend; if (sumlow < addend) ++sumhigh;
|
||||
#endif
|
||||
|
||||
#define MASK 0x00ff00ff
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#define lendian(i32) \
|
||||
(i32)
|
||||
#else
|
||||
#define lendian(i32) \
|
||||
(tmp = i32 >> 16 | i32 << 16, (tmp & MASK) << 8 | tmp >> 8 & MASK)
|
||||
#endif
|
||||
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
|
||||
#define lebytes(b4) \
|
||||
((b4)[3] << 24 | (b4)[2] << 16 | (b4)[1] << 8 | (b4)[0])
|
||||
|
||||
static void
|
||||
md5_prep_state_le(MD5Context *cx)
|
||||
{
|
||||
PRUint32 tmp;
|
||||
cx->u.w[0] = lendian(cx->u.w[0]);
|
||||
cx->u.w[1] = lendian(cx->u.w[1]);
|
||||
cx->u.w[2] = lendian(cx->u.w[2]);
|
||||
cx->u.w[3] = lendian(cx->u.w[3]);
|
||||
cx->u.w[4] = lendian(cx->u.w[4]);
|
||||
cx->u.w[5] = lendian(cx->u.w[5]);
|
||||
cx->u.w[6] = lendian(cx->u.w[6]);
|
||||
cx->u.w[7] = lendian(cx->u.w[7]);
|
||||
cx->u.w[8] = lendian(cx->u.w[8]);
|
||||
cx->u.w[9] = lendian(cx->u.w[9]);
|
||||
cx->u.w[10] = lendian(cx->u.w[10]);
|
||||
cx->u.w[11] = lendian(cx->u.w[11]);
|
||||
cx->u.w[12] = lendian(cx->u.w[12]);
|
||||
cx->u.w[13] = lendian(cx->u.w[13]);
|
||||
cx->u.w[14] = lendian(cx->u.w[14]);
|
||||
cx->u.w[15] = lendian(cx->u.w[15]);
|
||||
}
|
||||
|
||||
static void
|
||||
md5_prep_buffer_le(MD5Context *cx, const PRUint8 *beBuf)
|
||||
{
|
||||
cx->u.w[0] = lebytes(&beBuf[0]);
|
||||
cx->u.w[1] = lebytes(&beBuf[4]);
|
||||
cx->u.w[2] = lebytes(&beBuf[8]);
|
||||
cx->u.w[3] = lebytes(&beBuf[12]);
|
||||
cx->u.w[4] = lebytes(&beBuf[16]);
|
||||
cx->u.w[5] = lebytes(&beBuf[20]);
|
||||
cx->u.w[6] = lebytes(&beBuf[24]);
|
||||
cx->u.w[7] = lebytes(&beBuf[28]);
|
||||
cx->u.w[8] = lebytes(&beBuf[32]);
|
||||
cx->u.w[9] = lebytes(&beBuf[36]);
|
||||
cx->u.w[10] = lebytes(&beBuf[40]);
|
||||
cx->u.w[11] = lebytes(&beBuf[44]);
|
||||
cx->u.w[12] = lebytes(&beBuf[48]);
|
||||
cx->u.w[13] = lebytes(&beBuf[52]);
|
||||
cx->u.w[14] = lebytes(&beBuf[56]);
|
||||
cx->u.w[15] = lebytes(&beBuf[60]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define F(X, Y, Z) \
|
||||
((X & Y) | ((~X) & Z))
|
||||
|
||||
#define G(X, Y, Z) \
|
||||
((X & Z) | (Y & (~Z)))
|
||||
|
||||
#define H(X, Y, Z) \
|
||||
(X ^ Y ^ Z)
|
||||
|
||||
#define I(X, Y, Z) \
|
||||
(Y ^ (X | (~Z)))
|
||||
|
||||
#define FF(a, b, c, d, bufint, s, ti) \
|
||||
a = b + cls(a + F(b, c, d) + bufint + ti, s)
|
||||
|
||||
#define GG(a, b, c, d, bufint, s, ti) \
|
||||
a = b + cls(a + G(b, c, d) + bufint + ti, s)
|
||||
|
||||
#define HH(a, b, c, d, bufint, s, ti) \
|
||||
a = b + cls(a + H(b, c, d) + bufint + ti, s)
|
||||
|
||||
#define II(a, b, c, d, bufint, s, ti) \
|
||||
a = b + cls(a + I(b, c, d) + bufint + ti, s)
|
||||
|
||||
static void
|
||||
md5_compress(MD5Context *cx, const PRUint32 *wBuf)
|
||||
{
|
||||
PRUint32 a, b, c, d;
|
||||
PRUint32 tmp;
|
||||
a = cx->cv[0];
|
||||
b = cx->cv[1];
|
||||
c = cx->cv[2];
|
||||
d = cx->cv[3];
|
||||
FF(a, b, c, d, wBuf[R1B0 ], S1_0, T1_0);
|
||||
FF(d, a, b, c, wBuf[R1B1 ], S1_1, T1_1);
|
||||
FF(c, d, a, b, wBuf[R1B2 ], S1_2, T1_2);
|
||||
FF(b, c, d, a, wBuf[R1B3 ], S1_3, T1_3);
|
||||
FF(a, b, c, d, wBuf[R1B4 ], S1_0, T1_4);
|
||||
FF(d, a, b, c, wBuf[R1B5 ], S1_1, T1_5);
|
||||
FF(c, d, a, b, wBuf[R1B6 ], S1_2, T1_6);
|
||||
FF(b, c, d, a, wBuf[R1B7 ], S1_3, T1_7);
|
||||
FF(a, b, c, d, wBuf[R1B8 ], S1_0, T1_8);
|
||||
FF(d, a, b, c, wBuf[R1B9 ], S1_1, T1_9);
|
||||
FF(c, d, a, b, wBuf[R1B10], S1_2, T1_10);
|
||||
FF(b, c, d, a, wBuf[R1B11], S1_3, T1_11);
|
||||
FF(a, b, c, d, wBuf[R1B12], S1_0, T1_12);
|
||||
FF(d, a, b, c, wBuf[R1B13], S1_1, T1_13);
|
||||
FF(c, d, a, b, wBuf[R1B14], S1_2, T1_14);
|
||||
FF(b, c, d, a, wBuf[R1B15], S1_3, T1_15);
|
||||
GG(a, b, c, d, wBuf[R2B0 ], S2_0, T2_0);
|
||||
GG(d, a, b, c, wBuf[R2B1 ], S2_1, T2_1);
|
||||
GG(c, d, a, b, wBuf[R2B2 ], S2_2, T2_2);
|
||||
GG(b, c, d, a, wBuf[R2B3 ], S2_3, T2_3);
|
||||
GG(a, b, c, d, wBuf[R2B4 ], S2_0, T2_4);
|
||||
GG(d, a, b, c, wBuf[R2B5 ], S2_1, T2_5);
|
||||
GG(c, d, a, b, wBuf[R2B6 ], S2_2, T2_6);
|
||||
GG(b, c, d, a, wBuf[R2B7 ], S2_3, T2_7);
|
||||
GG(a, b, c, d, wBuf[R2B8 ], S2_0, T2_8);
|
||||
GG(d, a, b, c, wBuf[R2B9 ], S2_1, T2_9);
|
||||
GG(c, d, a, b, wBuf[R2B10], S2_2, T2_10);
|
||||
GG(b, c, d, a, wBuf[R2B11], S2_3, T2_11);
|
||||
GG(a, b, c, d, wBuf[R2B12], S2_0, T2_12);
|
||||
GG(d, a, b, c, wBuf[R2B13], S2_1, T2_13);
|
||||
GG(c, d, a, b, wBuf[R2B14], S2_2, T2_14);
|
||||
GG(b, c, d, a, wBuf[R2B15], S2_3, T2_15);
|
||||
HH(a, b, c, d, wBuf[R3B0 ], S3_0, T3_0);
|
||||
HH(d, a, b, c, wBuf[R3B1 ], S3_1, T3_1);
|
||||
HH(c, d, a, b, wBuf[R3B2 ], S3_2, T3_2);
|
||||
HH(b, c, d, a, wBuf[R3B3 ], S3_3, T3_3);
|
||||
HH(a, b, c, d, wBuf[R3B4 ], S3_0, T3_4);
|
||||
HH(d, a, b, c, wBuf[R3B5 ], S3_1, T3_5);
|
||||
HH(c, d, a, b, wBuf[R3B6 ], S3_2, T3_6);
|
||||
HH(b, c, d, a, wBuf[R3B7 ], S3_3, T3_7);
|
||||
HH(a, b, c, d, wBuf[R3B8 ], S3_0, T3_8);
|
||||
HH(d, a, b, c, wBuf[R3B9 ], S3_1, T3_9);
|
||||
HH(c, d, a, b, wBuf[R3B10], S3_2, T3_10);
|
||||
HH(b, c, d, a, wBuf[R3B11], S3_3, T3_11);
|
||||
HH(a, b, c, d, wBuf[R3B12], S3_0, T3_12);
|
||||
HH(d, a, b, c, wBuf[R3B13], S3_1, T3_13);
|
||||
HH(c, d, a, b, wBuf[R3B14], S3_2, T3_14);
|
||||
HH(b, c, d, a, wBuf[R3B15], S3_3, T3_15);
|
||||
II(a, b, c, d, wBuf[R4B0 ], S4_0, T4_0);
|
||||
II(d, a, b, c, wBuf[R4B1 ], S4_1, T4_1);
|
||||
II(c, d, a, b, wBuf[R4B2 ], S4_2, T4_2);
|
||||
II(b, c, d, a, wBuf[R4B3 ], S4_3, T4_3);
|
||||
II(a, b, c, d, wBuf[R4B4 ], S4_0, T4_4);
|
||||
II(d, a, b, c, wBuf[R4B5 ], S4_1, T4_5);
|
||||
II(c, d, a, b, wBuf[R4B6 ], S4_2, T4_6);
|
||||
II(b, c, d, a, wBuf[R4B7 ], S4_3, T4_7);
|
||||
II(a, b, c, d, wBuf[R4B8 ], S4_0, T4_8);
|
||||
II(d, a, b, c, wBuf[R4B9 ], S4_1, T4_9);
|
||||
II(c, d, a, b, wBuf[R4B10], S4_2, T4_10);
|
||||
II(b, c, d, a, wBuf[R4B11], S4_3, T4_11);
|
||||
II(a, b, c, d, wBuf[R4B12], S4_0, T4_12);
|
||||
II(d, a, b, c, wBuf[R4B13], S4_1, T4_13);
|
||||
II(c, d, a, b, wBuf[R4B14], S4_2, T4_14);
|
||||
II(b, c, d, a, wBuf[R4B15], S4_3, T4_15);
|
||||
cx->cv[0] += a;
|
||||
cx->cv[1] += b;
|
||||
cx->cv[2] += c;
|
||||
cx->cv[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
|
||||
{
|
||||
PRUint32 bytesToConsume;
|
||||
PRUint32 inBufIndex = cx->lsbInput & 63;
|
||||
const PRUint32 *wBuf;
|
||||
|
||||
/* Add the number of input bytes to the 64-bit input counter. */
|
||||
addto64(cx->msbInput, cx->lsbInput, inputLen);
|
||||
if (inBufIndex) {
|
||||
/* There is already data in the buffer. Fill with input. */
|
||||
bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - inBufIndex);
|
||||
memcpy(&cx->inBuf[inBufIndex], input, bytesToConsume);
|
||||
if (inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE) {
|
||||
/* The buffer is filled. Run the compression function. */
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
md5_prep_state_le(cx);
|
||||
#endif
|
||||
md5_compress(cx, cx->u.w);
|
||||
}
|
||||
/* Remaining input. */
|
||||
inputLen -= bytesToConsume;
|
||||
input += bytesToConsume;
|
||||
}
|
||||
|
||||
/* Iterate over 64-byte chunks of the message. */
|
||||
while (inputLen >= MD5_BUFFER_SIZE) {
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
#ifdef _X86_
|
||||
/* x86 can handle arithmetic on non-word-aligned buffers */
|
||||
wBuf = (PRUint32 *)input;
|
||||
#else
|
||||
if ((ptrdiff_t)input & 0x3) {
|
||||
/* buffer not aligned, copy it to force alignment */
|
||||
memcpy(cx->inBuf, input, MD5_BUFFER_SIZE);
|
||||
wBuf = cx->u.w;
|
||||
} else {
|
||||
/* buffer is aligned */
|
||||
wBuf = (PRUint32 *)input;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
md5_prep_buffer_le(cx, input);
|
||||
wBuf = cx->u.w;
|
||||
#endif
|
||||
md5_compress(cx, wBuf);
|
||||
inputLen -= MD5_BUFFER_SIZE;
|
||||
input += MD5_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* Tail of message (message bytes mod 64). */
|
||||
if (inputLen)
|
||||
memcpy(cx->inBuf, input, inputLen);
|
||||
}
|
||||
|
||||
static const unsigned char padbytes[] = {
|
||||
0x80, 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, 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, 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, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void
|
||||
MD5_End(MD5Context *cx, unsigned char *digest,
|
||||
unsigned int *digestLen, unsigned int maxDigestLen)
|
||||
{
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
PRUint32 tmp;
|
||||
#endif
|
||||
PRUint32 lowInput, highInput;
|
||||
PRUint32 inBufIndex = cx->lsbInput & 63;
|
||||
|
||||
if (maxDigestLen < MD5_HASH_LEN) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy out the length of bits input before padding. */
|
||||
lowInput = cx->lsbInput;
|
||||
highInput = (cx->msbInput << 3) | (lowInput >> 29);
|
||||
lowInput <<= 3;
|
||||
|
||||
if (inBufIndex < MD5_END_BUFFER) {
|
||||
MD5_Update(cx, padbytes, MD5_END_BUFFER - inBufIndex);
|
||||
} else {
|
||||
MD5_Update(cx, padbytes,
|
||||
MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex);
|
||||
}
|
||||
|
||||
/* Store the number of bytes input (before padding) in final 64 bits. */
|
||||
cx->u.w[14] = lendian(lowInput);
|
||||
cx->u.w[15] = lendian(highInput);
|
||||
|
||||
/* Final call to compress. */
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
md5_prep_state_le(cx);
|
||||
#endif
|
||||
md5_compress(cx, cx->u.w);
|
||||
|
||||
/* Copy the resulting values out of the chain variables into return buf. */
|
||||
*digestLen = MD5_HASH_LEN;
|
||||
#ifndef IS_LITTLE_ENDIAN
|
||||
cx->cv[0] = lendian(cx->cv[0]);
|
||||
cx->cv[1] = lendian(cx->cv[1]);
|
||||
cx->cv[2] = lendian(cx->cv[2]);
|
||||
cx->cv[3] = lendian(cx->cv[3]);
|
||||
#endif
|
||||
memcpy(digest, cx->cv, MD5_HASH_LEN);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
MD5_FlattenSize(MD5Context *cx)
|
||||
{
|
||||
return sizeof(*cx);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
MD5_Flatten(MD5Context *cx, unsigned char *space)
|
||||
{
|
||||
memcpy(space, cx, sizeof(*cx));
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
MD5Context *
|
||||
MD5_Resurrect(unsigned char *space, void *arg)
|
||||
{
|
||||
MD5Context *cx = MD5_NewContext();
|
||||
if (cx)
|
||||
memcpy(cx, space, sizeof(*cx));
|
||||
return cx;
|
||||
}
|
||||
|
||||
void MD5_Clone(MD5Context *dest, MD5Context *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof *dest);
|
||||
}
|
||||
|
||||
void
|
||||
MD5_TraceState(MD5Context *cx)
|
||||
{
|
||||
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
* mknewpc2.c
|
||||
*
|
||||
* Generate PC-2 tables for DES-150 library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned int HALF;
|
||||
|
||||
#define DES_ENCRYPT 0
|
||||
#define DES_DECRYPT 1
|
||||
|
||||
/* two 28-bit registers defined in key schedule production process */
|
||||
static HALF C0, D0;
|
||||
|
||||
static HALF L0, R0;
|
||||
|
||||
/* key schedule, 16 internal keys, each with 8 6-bit parts */
|
||||
static BYTE KS [8] [16];
|
||||
|
||||
|
||||
/*
|
||||
* This table takes the 56 bits in C0 and D0 and shows show they are
|
||||
* permuted into the 8 6-bit parts of the key in the key schedule.
|
||||
* The bits of C0 are numbered left to right, 1-28.
|
||||
* The bits of D0 are numbered left to right, 29-56.
|
||||
* Zeros in this table represent bits that are always zero.
|
||||
* Note that all the bits in the first 4 rows come from C0,
|
||||
* and all the bits in the second 4 rows come from D0.
|
||||
*/
|
||||
static const BYTE PC2[64] = {
|
||||
14, 17, 11, 24, 1, 5, 0, 0, /* S1 */
|
||||
3, 28, 15, 6, 21, 10, 0, 0, /* S2 */
|
||||
23, 19, 12, 4, 26, 8, 0, 0, /* S3 */
|
||||
16, 7, 27, 20, 13, 2, 0, 0, /* S4 */
|
||||
|
||||
41, 52, 31, 37, 47, 55, 0, 0, /* S5 */
|
||||
30, 40, 51, 45, 33, 48, 0, 0, /* S6 */
|
||||
44, 49, 39, 56, 34, 53, 0, 0, /* S7 */
|
||||
46, 42, 50, 36, 29, 32, 0, 0 /* S8 */
|
||||
};
|
||||
|
||||
/* This table represents the same info as PC2, except that
|
||||
* The bits of C0 and D0 are each numbered right to left, 0-27.
|
||||
* -1 values indicate bits that are always zero.
|
||||
* As before all the bits in the first 4 rows come from C0,
|
||||
* and all the bits in the second 4 rows come from D0.
|
||||
*/
|
||||
static signed char PC2a[64] = {
|
||||
/* bits of C0 */
|
||||
14, 11, 17, 4, 27, 23, -1, -1, /* S1 */
|
||||
25, 0, 13, 22, 7, 18, -1, -1, /* S2 */
|
||||
5, 9, 16, 24, 2, 20, -1, -1, /* S3 */
|
||||
12, 21, 1, 8, 15, 26, -1, -1, /* S4 */
|
||||
/* bits of D0 */
|
||||
15, 4, 25, 19, 9, 1, -1, -1, /* S5 */
|
||||
26, 16, 5, 11, 23, 8, -1, -1, /* S6 */
|
||||
12, 7, 17, 0, 22, 3, -1, -1, /* S7 */
|
||||
10, 14, 6, 20, 27, 24, -1, -1 /* S8 */
|
||||
};
|
||||
|
||||
/* This table represents the same info as PC2a, except that
|
||||
* The order of of the rows has been changed to increase the efficiency
|
||||
* with which the key sechedule is created.
|
||||
* Fewer shifts and ANDs are required to make the KS from these.
|
||||
*/
|
||||
static const signed char PC2b[64] = {
|
||||
/* bits of C0 */
|
||||
14, 11, 17, 4, 27, 23, -1, -1, /* S1 */
|
||||
5, 9, 16, 24, 2, 20, -1, -1, /* S3 */
|
||||
25, 0, 13, 22, 7, 18, -1, -1, /* S2 */
|
||||
12, 21, 1, 8, 15, 26, -1, -1, /* S4 */
|
||||
/* bits of D0 */
|
||||
26, 16, 5, 11, 23, 8, -1, -1, /* S6 */
|
||||
10, 14, 6, 20, 27, 24, -1, -1, /* S8 */
|
||||
15, 4, 25, 19, 9, 1, -1, -1, /* S5 */
|
||||
12, 7, 17, 0, 22, 3, -1, -1 /* S7 */
|
||||
};
|
||||
|
||||
/* Only 24 of the 28 bits in C0 and D0 are used in PC2.
|
||||
* The used bits of C0 and D0 are grouped into 4 groups of 6,
|
||||
* so that the PC2 permutation can be accomplished with 4 lookups
|
||||
* in tables of 64 entries.
|
||||
* The following table shows how the bits of C0 and D0 are grouped
|
||||
* into indexes for the respective table lookups.
|
||||
* Bits are numbered right-to-left, 0-27, as in PC2b.
|
||||
*/
|
||||
static BYTE NDX[48] = {
|
||||
/* Bits of C0 */
|
||||
27, 26, 25, 24, 23, 22, /* C0 table 0 */
|
||||
18, 17, 16, 15, 14, 13, /* C0 table 1 */
|
||||
9, 8, 7, 2, 1, 0, /* C0 table 2 */
|
||||
5, 4, 21, 20, 12, 11, /* C0 table 3 */
|
||||
/* bits of D0 */
|
||||
27, 26, 25, 24, 23, 22, /* D0 table 0 */
|
||||
20, 19, 17, 16, 15, 14, /* D0 table 1 */
|
||||
12, 11, 10, 9, 8, 7, /* D0 table 2 */
|
||||
6, 5, 4, 3, 1, 0 /* D0 table 3 */
|
||||
};
|
||||
|
||||
/* Here's the code that does that grouping.
|
||||
left = PC2LOOKUP(0, 0, ((c0 >> 22) & 0x3F) );
|
||||
left |= PC2LOOKUP(0, 1, ((c0 >> 13) & 0x3F) );
|
||||
left |= PC2LOOKUP(0, 2, ((c0 >> 4) & 0x38) | (c0 & 0x7) );
|
||||
left |= PC2LOOKUP(0, 3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
|
||||
|
||||
right = PC2LOOKUP(1, 0, ((d0 >> 22) & 0x3F) );
|
||||
right |= PC2LOOKUP(1, 1, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
|
||||
right |= PC2LOOKUP(1, 2, ((d0 >> 7) & 0x3F) );
|
||||
right |= PC2LOOKUP(1, 3, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
|
||||
*/
|
||||
|
||||
void
|
||||
make_pc2a( void )
|
||||
{
|
||||
|
||||
int i, j;
|
||||
|
||||
for ( i = 0; i < 64; ++i ) {
|
||||
j = PC2[i];
|
||||
if (j == 0)
|
||||
j = -1;
|
||||
else if ( j < 29 )
|
||||
j = 28 - j ;
|
||||
else
|
||||
j = 56 - j;
|
||||
PC2a[i] = j;
|
||||
}
|
||||
for ( i = 0; i < 64; i += 8 ) {
|
||||
printf("%3d,%3d,%3d,%3d,%3d,%3d,%3d,%3d,\n",
|
||||
PC2a[i+0],PC2a[i+1],PC2a[i+2],PC2a[i+3],
|
||||
PC2a[i+4],PC2a[i+5],PC2a[i+6],PC2a[i+7] );
|
||||
}
|
||||
}
|
||||
|
||||
HALF PC2cd0[64];
|
||||
|
||||
HALF PC_2H[8][64];
|
||||
|
||||
void
|
||||
mktable( )
|
||||
{
|
||||
int i;
|
||||
int table;
|
||||
const BYTE * ndx = NDX;
|
||||
HALF mask;
|
||||
|
||||
mask = 0x80000000;
|
||||
for (i = 0; i < 32; ++i, mask >>= 1) {
|
||||
int bit = PC2b[i];
|
||||
if (bit < 0)
|
||||
continue;
|
||||
PC2cd0[bit + 32] = mask;
|
||||
}
|
||||
|
||||
mask = 0x80000000;
|
||||
for (i = 32; i < 64; ++i, mask >>= 1) {
|
||||
int bit = PC2b[i];
|
||||
if (bit < 0)
|
||||
continue;
|
||||
PC2cd0[bit] = mask;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
for (i = 0; i < 64; ++i) {
|
||||
printf("0x%08x,\n", PC2cd0[i]);
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < 24; ++i) {
|
||||
NDX[i] += 32; /* because c0 is the upper half */
|
||||
}
|
||||
|
||||
for (table = 0; table < 8; ++table) {
|
||||
HALF bitvals[6];
|
||||
for (i = 0; i < 6; ++i) {
|
||||
bitvals[5-i] = PC2cd0[*ndx++];
|
||||
}
|
||||
for (i = 0; i < 64; ++i) {
|
||||
int j;
|
||||
int k = 0;
|
||||
HALF value = 0;
|
||||
|
||||
for (j = i; j; j >>= 1, ++k) {
|
||||
if (j & 1) {
|
||||
value |= bitvals[k];
|
||||
}
|
||||
}
|
||||
PC_2H[table][i] = value;
|
||||
}
|
||||
printf("/* table %d */ {\n", table );
|
||||
for (i = 0; i < 64; i += 4) {
|
||||
printf(" 0x%08x, 0x%08x, 0x%08x, 0x%08x, \n",
|
||||
PC_2H[table][i], PC_2H[table][i+1],
|
||||
PC_2H[table][i+2], PC_2H[table][i+3]);
|
||||
}
|
||||
printf(" },\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* make_pc2a(); */
|
||||
mktable();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* mksp.c
|
||||
*
|
||||
* Generate SP tables for DES-150 library
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the DES-150 library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Nelson B. Bolyard, nelsonb@iname.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1990
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* sboxes - the tables for the s-box functions
|
||||
* from FIPS 46, pages 15-16.
|
||||
*/
|
||||
unsigned char S[8][64] = {
|
||||
/* Func S1 = */ {
|
||||
14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
|
||||
3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
|
||||
4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
|
||||
15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
|
||||
},
|
||||
/* Func S2 = */ {
|
||||
15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
|
||||
9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
|
||||
0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
|
||||
5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
|
||||
},
|
||||
/* Func S3 = */ {
|
||||
10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
|
||||
1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
|
||||
13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
|
||||
11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
|
||||
},
|
||||
/* Func S4 = */ {
|
||||
7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
|
||||
1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
|
||||
10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
|
||||
15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
|
||||
},
|
||||
/* Func S5 = */ {
|
||||
2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
|
||||
8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
|
||||
4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
|
||||
15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
|
||||
},
|
||||
/* Func S6 = */ {
|
||||
12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
|
||||
0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
|
||||
9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
|
||||
7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
|
||||
},
|
||||
/* Func S7 = */ {
|
||||
4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
|
||||
3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
|
||||
1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
|
||||
10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
|
||||
},
|
||||
/* Func S8 = */ {
|
||||
13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
|
||||
10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
|
||||
7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
|
||||
0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Permutation function for results from s-boxes
|
||||
* from FIPS 46 pages 12 and 16.
|
||||
* P =
|
||||
*/
|
||||
unsigned char P[32] = {
|
||||
16, 7, 20, 21, 29, 12, 28, 17,
|
||||
1, 15, 23, 26, 5, 18, 31, 10,
|
||||
2, 8, 24, 14, 32, 27, 3, 9,
|
||||
19, 13, 30, 6, 22, 11, 4, 25
|
||||
};
|
||||
|
||||
unsigned int Pinv[32];
|
||||
unsigned int SP[8][64];
|
||||
|
||||
void
|
||||
makePinv(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int Pi = 0x80000000;
|
||||
for (i = 0; i < 32; ++i) {
|
||||
int j = 32 - P[i];
|
||||
Pinv[j] = Pi;
|
||||
Pi >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
makeSP(void)
|
||||
{
|
||||
int box;
|
||||
for (box = 0; box < 8; ++box) {
|
||||
int item;
|
||||
printf("/* box S%d */ {\n", box + 1);
|
||||
for (item = 0; item < 64; ++item ) {
|
||||
unsigned int s = S[box][item];
|
||||
unsigned int val = 0;
|
||||
unsigned int bitnum = (7-box) * 4;
|
||||
for (; s; s >>= 1, ++bitnum) {
|
||||
if (s & 1) {
|
||||
val |= Pinv[bitnum];
|
||||
}
|
||||
}
|
||||
val = (val << 3) | (val >> 29);
|
||||
SP[box][item] = val;
|
||||
}
|
||||
for (item = 0; item < 64; item += 4) {
|
||||
printf("\t0x%08x, 0x%08x, 0x%08x, 0x%08x,\n",
|
||||
SP[box][item], SP[box][item+1], SP[box][item+2], SP[box][item+3]);
|
||||
}
|
||||
printf(" },\n");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
makePinv();
|
||||
makeSP();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
#
|
||||
# Makefile for MPI library
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
# Richard C. Swift (swift@netscape.com)
|
||||
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile,v 1.26 2007-05-09 00:09:37 neil.williams%sun.com Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
include target.mk
|
||||
|
||||
CFLAGS+= $(XCFLAGS)
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c \
|
||||
mpcpucache.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \
|
||||
mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
|
||||
basecvt fact exptmod pi makeprime identest
|
||||
|
||||
LIBOBJS = mpprime.o mpmontg.o mplogic.o mp_gf2m.o mpi.o mpcpucache.o $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mp_gf2m.h mpprime.h
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "libmpi.a - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .o .i
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
#.c.o: $*.h $*.c
|
||||
# $(CC) $(CFLAGS) -c $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.o: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS)
|
||||
|
||||
mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.o: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpcpucache.o: mpcpucache.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.o: mpi_mips.s
|
||||
$(CC) -o $@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi_sparc.o : montmulf.h
|
||||
|
||||
mpv_sparcv9.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_64.il mpv_sparc.c
|
||||
|
||||
mpv_sparcv8.s: vis_64.il mpv_sparc.c
|
||||
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_32.il mpv_sparc.c
|
||||
|
||||
montmulfv8.o montmulfv9.o mpv_sparcv8.o mpv_sparcv9.o : %.o : %.s
|
||||
$(CC) -o $@ $(SOLARIS_ASM_FLAGS) -c $<
|
||||
|
||||
# This rule is used to build the .s sources, which are then hand optimized.
|
||||
#montmulfv8.s montmulfv9.s : montmulf%.s : montmulf%.il montmulf.c montmulf.h
|
||||
# $(CC) -o $@ $(SOLARIS_ASM_FLAGS) -S montmulf$*.il montmulf.c
|
||||
|
||||
|
||||
libmpi.a: $(LIBOBJS)
|
||||
ar -cvr libmpi.a $(LIBOBJS)
|
||||
$(RANLIB) libmpi.a
|
||||
|
||||
lib libs: libmpi.a
|
||||
|
||||
mpi.i: mpi.h
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
|
||||
mptest4b.o mptest6.o mptest7.o mptest8.o mptest9.o mptestb.o
|
||||
MPTESTS = $(MPTESTOBJS:.o=)
|
||||
|
||||
$(MPTESTOBJS): mptest%.o: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%: mptest%.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b mptest6 \
|
||||
mptestb bbsrand
|
||||
|
||||
utests: mptest7 mptest8 mptest9
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.o bbs_rand.o prng.o
|
||||
UTILOBJS = primegen.o metime.o identest.o basecvt.o fact.o exptmod.o pi.o \
|
||||
makeprime.o gcd.o invmod.o lap.o isprime.o \
|
||||
dec2hex.o hex2dec.o
|
||||
UTILS = $(UTILOBJS:.o=)
|
||||
|
||||
$(UTILS): % : %.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.o : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
prng: prng.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
bbsrand: bbsrand.o bbs_rand.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
utils: $(UTILS) prng bbsrand
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.o: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
mpi-test: mpi-test.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mdxptest.o: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest: mdxptest.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
mulsqr.o: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o $@ -c mulsqr.c
|
||||
|
||||
mulsqr: mulsqr.o libmpi.a
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.i
|
||||
rm -f core
|
||||
rm -f *~ .*~
|
||||
rm -f utils/*.o
|
||||
rm -f utils/core
|
||||
rm -f utils/*~ utils/.*~
|
||||
|
||||
clobber: clean
|
||||
rm -f $(TOOLS) $(UTILS)
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f libmpi.a
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
# END
|
||||
@@ -1,280 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with VACPP on OS/2
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.os2,v 1.6 2007-05-09 00:09:37 neil.williams%sun.com Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=icc.exe
|
||||
AS=alp.exe
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
|
||||
|
||||
#OS/2
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = /Ti+ -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
$(MPICMN)
|
||||
ASFLAGS =
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test.exe - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ilib /out:mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,291 +0,0 @@
|
||||
#
|
||||
# Makefile.win - gmake Makefile for building MPI with MSVC on NT
|
||||
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#
|
||||
# $Id: Makefile.win,v 1.6.12.1 2008-03-02 05:41:42 nelson%bolyard.com Exp $
|
||||
#
|
||||
|
||||
## Define CC to be the C compiler you wish to use. The GNU cc
|
||||
## compiler (gcc) should work, at the very least
|
||||
#CC=cc
|
||||
#CC=gcc
|
||||
CC=cl.exe
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
AS=ml64.exe
|
||||
else
|
||||
AS=ml.exe
|
||||
endif
|
||||
|
||||
##
|
||||
## Define PERL to point to your local Perl interpreter. It
|
||||
## should be Perl 5.x, although it's conceivable that Perl 4
|
||||
## might work ... I haven't tested it.
|
||||
##
|
||||
#PERL=/usr/bin/perl
|
||||
#PERL=perl
|
||||
|
||||
##
|
||||
## Define CFLAGS to contain any local options your compiler
|
||||
## setup requires.
|
||||
##
|
||||
## Conditional compilation options are no longer here; see
|
||||
## the file 'mpi-config.h' instead.
|
||||
##
|
||||
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
|
||||
|
||||
ifeq ($(CPU_ARCH),x86_64)
|
||||
AS_SRCS = mpi_x86_64.asm
|
||||
CFLAGS = -O2 -Z7 -MD -W3 -nologo -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WIN64 -D_AMD64_ -D_M_AMD64 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
ASFLAGS = -Cp -Sn -Zi -I.
|
||||
else
|
||||
#NT
|
||||
AS_SRCS = mpi_x86.asm
|
||||
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
|
||||
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
|
||||
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
CFLAGS = -O2 -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
|
||||
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
|
||||
ASFLAGS = -Cp -Sn -Zi -coff -I.
|
||||
endif
|
||||
|
||||
##
|
||||
## Define LIBS to include any libraries you need to link against.
|
||||
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
|
||||
## necessary to bring in the math library. Otherwise, it can be
|
||||
## left alone, unless your system has other peculiar requirements.
|
||||
##
|
||||
LIBS=#-lmalloc#-lefence#-lm
|
||||
|
||||
##
|
||||
## Define RANLIB to be the library header randomizer; you might not
|
||||
## need this on some systems (just set it to 'echo' on these systems,
|
||||
## such as IRIX)
|
||||
##
|
||||
RANLIB=echo
|
||||
|
||||
##
|
||||
## This is the version string used for the documentation and
|
||||
## building the distribution tarball. Don't mess with it unless
|
||||
## you are releasing a new version
|
||||
VERS=1.7p6
|
||||
|
||||
## ----------------------------------------------------------------------
|
||||
## You probably don't need to change anything below this line...
|
||||
##
|
||||
|
||||
##
|
||||
## This is the list of source files that need to be packed into
|
||||
## the distribution file
|
||||
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
|
||||
utils/gcd.c utils/invmod.c utils/lap.c \
|
||||
utils/ptab.pl utils/sieve.c utils/isprime.c\
|
||||
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
|
||||
utils/bbsrand.c utils/prng.c utils/primegen.c \
|
||||
utils/basecvt.c utils/makeprime.c\
|
||||
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
|
||||
utils/mpi.h utils/mpprime.h mulsqr.c \
|
||||
make-test-arrays test-arrays.txt all-tests make-logtab \
|
||||
types.pl stats timetest multest
|
||||
|
||||
## These are the header files that go into the distribution file
|
||||
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
|
||||
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
|
||||
|
||||
## These are the documentation files that go into the distribution file
|
||||
DOCS=README doc utils/README utils/PRIMES
|
||||
|
||||
## This is the list of tools built by 'make tools'
|
||||
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
|
||||
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
|
||||
|
||||
AS_OBJS = $(AS_SRCS:.asm=.obj)
|
||||
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
|
||||
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
|
||||
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
|
||||
|
||||
|
||||
help:
|
||||
@ echo ""
|
||||
@ echo "The following targets can be built with this Makefile:"
|
||||
@ echo ""
|
||||
@ echo "mpi.lib - arithmetic and prime testing library"
|
||||
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
|
||||
@ echo "tools - command line tools"
|
||||
@ echo "doc - manual pages for tools"
|
||||
@ echo "clean - clean up objects and such"
|
||||
@ echo "distclean - get ready for distribution"
|
||||
@ echo "dist - distribution tarball"
|
||||
@ echo ""
|
||||
|
||||
.SUFFIXES: .c .obj .i .lib .exe .asm
|
||||
|
||||
.c.i:
|
||||
$(CC) $(CFLAGS) -E $< > $@
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
.asm.obj:
|
||||
$(AS) $(ASFLAGS) -c $<
|
||||
|
||||
.obj.exe:
|
||||
$(CC) $(CFLAGS) -Fo$@ $<
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
$(LIBOBJS): $(LIBHDRS)
|
||||
|
||||
logtab.h: make-logtab
|
||||
$(PERL) make-logtab > logtab.h
|
||||
|
||||
mpi.obj: mpi.c logtab.h $(LIBHDRS)
|
||||
|
||||
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
|
||||
|
||||
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
|
||||
|
||||
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
|
||||
|
||||
mpi_mips.obj: mpi_mips.s
|
||||
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
|
||||
|
||||
mpi.lib: $(LIBOBJS)
|
||||
ar -cvr mpi.lib $(LIBOBJS)
|
||||
$(RANLIB) mpi.lib
|
||||
|
||||
lib libs: mpi.lib
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
|
||||
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
|
||||
MPTESTS = $(MPTESTOBJS:.obj=.exe)
|
||||
|
||||
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
|
||||
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
|
||||
|
||||
utests: mptest7.exe mptest8.exe mptest9.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
|
||||
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
|
||||
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
|
||||
isprime.obj dec2hex.obj hex2dec.obj
|
||||
UTILS = $(UTILOBJS:.obj=.exe)
|
||||
|
||||
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
utils: $(UTILS) prng.exe bbsrand.exe
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
test-info.c: test-arrays.txt
|
||||
$(PERL) make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
|
||||
|
||||
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
|
||||
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
|
||||
|
||||
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
|
||||
$(CC) $(CFLAGS) -Fo$@ $^
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
alltests: tests utests mpi-test.exe
|
||||
|
||||
tools: $(TOOLS)
|
||||
|
||||
doc:
|
||||
(cd doc; ./build)
|
||||
|
||||
clean:
|
||||
rm -f *.obj *.lib *.pdb *.ilk
|
||||
cd utils; rm -f *.obj *.lib *.pdb *.ilk
|
||||
|
||||
distclean: clean
|
||||
rm -f mptest? mpi-test metime mulsqr karatsuba
|
||||
rm -f mptest?a mptest?b
|
||||
rm -f utils/mptest?
|
||||
rm -f test-info.c logtab.h
|
||||
rm -f mpi.lib
|
||||
rm -f $(TOOLS)
|
||||
|
||||
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
|
||||
pgps -ab mpi-$(VERS).tar
|
||||
chmod +r mpi-$(VERS).tar.asc
|
||||
gzip -9 mpi-$(VERS).tar
|
||||
|
||||
|
||||
print:
|
||||
@echo LIBOBJS = $(LIBOBJS)
|
||||
# END
|
||||
@@ -1,799 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1997-2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
About the MPI Library
|
||||
---------------------
|
||||
|
||||
The files 'mpi.h' and 'mpi.c' define a simple, arbitrary precision
|
||||
signed integer arithmetic package. The implementation is not the most
|
||||
efficient possible, but the code is small and should be fairly easily
|
||||
portable to just about any machine that supports an ANSI C compiler,
|
||||
as long as it is capable of at least 16-bit arithmetic (but also see
|
||||
below for more on this).
|
||||
|
||||
This library was written with an eye to cryptographic applications;
|
||||
thus, some care is taken to make sure that temporary values are not
|
||||
left lying around in memory when they are no longer in use. This adds
|
||||
some overhead for zeroing buffers before they are released back into
|
||||
the free pool; however, it gives you the assurance that there is only
|
||||
one copy of your important values residing in your process's address
|
||||
space at a time. Obviously, it is difficult to guarantee anything, in
|
||||
a pre-emptive multitasking environment, but this at least helps you
|
||||
keep a lid on the more obvious ways your data can get spread around in
|
||||
memory.
|
||||
|
||||
|
||||
Using the Library
|
||||
-----------------
|
||||
|
||||
To use the MPI library in your program, you must include the header:
|
||||
|
||||
#include "mpi.h"
|
||||
|
||||
This header provides all the type and function declarations you'll
|
||||
need to use the library. Almost all the names defined by the library
|
||||
begin with the prefix 'mp_', so it should be easy to keep them from
|
||||
clashing with your program's namespace (he says, glibly, knowing full
|
||||
well there are always pathological cases).
|
||||
|
||||
There are a few things you may want to configure about the library.
|
||||
By default, the MPI library uses an unsigned short for its digit type,
|
||||
and an unsigned int for its word type. The word type must be big
|
||||
enough to contain at least two digits, for the primitive arithmetic to
|
||||
work out. On my machine, a short is 2 bytes and an int is 4 bytes --
|
||||
but if you have 64-bit ints, you might want to use a 4-byte digit and
|
||||
an 8-byte word. I have tested the library using 1-byte digits and
|
||||
2-byte words, as well. Whatever you choose to do, the things you need
|
||||
to change are:
|
||||
|
||||
(1) The type definitions for mp_digit and mp_word.
|
||||
|
||||
(2) The macro DIGIT_FMT which tells mp_print() how to display a
|
||||
single digit. This is just a printf() format string, so you
|
||||
can adjust it appropriately.
|
||||
|
||||
(3) The macros DIGIT_MAX and MP_WORD_MAX, which specify the
|
||||
largest value expressible in an mp_digit and an mp_word,
|
||||
respectively.
|
||||
|
||||
Both the mp_digit and mp_word should be UNSIGNED integer types. The
|
||||
code relies on having the full positive precision of the type used for
|
||||
digits and words.
|
||||
|
||||
The remaining type definitions should be left alone, for the most
|
||||
part. The code in the library does not make any significant
|
||||
assumptions about the sizes of things, but there is little if any
|
||||
reason to change the other parameters, so I would recommend you leave
|
||||
them as you found them.
|
||||
|
||||
The library comes with a Perl script, 'types.pl', which will scan your
|
||||
current Makefile settings, and attempt to find good definitions for
|
||||
these types. It relies on a Unix sort of build environment, so it
|
||||
probably won't work under MacOS or Windows, but it can be convenient
|
||||
if you're porting to a new flavour of Unix. Just run 'types.pl' at
|
||||
the command line, and it will spit out its results to the standard
|
||||
output.
|
||||
|
||||
|
||||
Conventions
|
||||
-----------
|
||||
|
||||
Most functions in the library return a value of type mp_err. This
|
||||
permits the library to communicate success or various kinds of failure
|
||||
to the calling program. The return values currently defined are:
|
||||
|
||||
MP_OKAY - okay, operation succeeded, all's well
|
||||
MP_YES - okay, the answer is yes (same as MP_OKAY)
|
||||
MP_NO - okay, but answer is no (not MP_OKAY)
|
||||
MP_MEM - operation ran out of memory
|
||||
MP_RANGE - input parameter was out of range
|
||||
MP_BADARG - an invalid input parameter was provided
|
||||
MP_UNDEF - no output value is defined for this input
|
||||
|
||||
The only function which currently uses MP_UNDEF is mp_invmod().
|
||||
Division by zero is undefined, but the division functions will return
|
||||
MP_RANGE for a zero divisor. MP_BADARG usually means you passed a
|
||||
bogus mp_int structure to the function. MP_YES and MP_NO are not used
|
||||
by the library itself; they're defined so you can use them in your own
|
||||
extensions.
|
||||
|
||||
If you need a readable interpretation of these error codes in your
|
||||
program, you may also use the mp_strerror() function. This function
|
||||
takes an mp_err as input, and returns a pointer to a human-readable
|
||||
string describing the meaning of the error. These strings are stored
|
||||
as constants within the library, so the caller should not attempt to
|
||||
modify or free the memory associated with these strings.
|
||||
|
||||
The library represents values in signed-magnitude format. Values
|
||||
strictly less than zero are negative, all others are considered
|
||||
positive (zero is positive by fiat). You can access the 'sign' member
|
||||
of the mp_int structure directly, but better is to use the mp_cmp_z()
|
||||
function, to find out which side of zero the value lies on.
|
||||
|
||||
Most arithmetic functions have a single-digit variant, as well as the
|
||||
full arbitrary-precision. An mp_digit is an unsigned value between 0
|
||||
and DIGIT_MAX inclusive. The radix is available as RADIX. The number
|
||||
of bits in a given digit is given as DIGIT_BIT.
|
||||
|
||||
Generally, input parameters are given before output parameters.
|
||||
Unless otherwise specified, any input parameter can be re-used as an
|
||||
output parameter, without confusing anything.
|
||||
|
||||
The basic numeric type defined by the library is an mp_int. Virtually
|
||||
all the functions in the library take a pointer to an mp_int as one of
|
||||
their parameters. An explanation of how to create and use these
|
||||
<HR>
|
||||
<A NAME="p23">
|
||||
<H3>Problem 23:</H3>
|
||||
|
||||
structures follows. And so, without further ado...
|
||||
|
||||
|
||||
Initialization and Cleanup
|
||||
--------------------------
|
||||
|
||||
The basic numeric type defined by the library is an 'mp_int'.
|
||||
However, it is not sufficient to simply declare a variable of type
|
||||
mp_int in your program. These variables also need to be initialized
|
||||
before they can be used, to allocate the internal storage they require
|
||||
for computation.
|
||||
|
||||
This is done using one of the following functions:
|
||||
|
||||
mp_init(mp_int *mp);
|
||||
mp_init_copy(mp_int *mp, mp_int *from);
|
||||
mp_init_size(mp_int *mp, mp_size p);
|
||||
|
||||
Each of these requires a pointer to a structure of type mp_int. The
|
||||
basic mp_init() simply initializes the mp_int to a default size, and
|
||||
sets its value to zero. If you would like to initialize a copy of an
|
||||
existing mp_int, use mp_init_copy(), where the 'from' parameter is the
|
||||
mp_int you'd like to make a copy of. The third function,
|
||||
mp_init_size(), permits you to specify how many digits of precision
|
||||
should be preallocated for your mp_int. This can help the library
|
||||
avoid unnecessary re-allocations later on.
|
||||
|
||||
The default precision used by mp_init() can be retrieved using:
|
||||
|
||||
precision = mp_get_prec();
|
||||
|
||||
This returns the number of digits that will be allocated. You can
|
||||
change this value by using:
|
||||
|
||||
mp_set_prec(unsigned int prec);
|
||||
|
||||
Any positive value is acceptable -- if you pass zero, the default
|
||||
precision will be re-set to the compiled-in library default (this is
|
||||
specified in the header file 'mpi-config.h', and typically defaults to
|
||||
8 or 16).
|
||||
|
||||
Just as you must allocate an mp_int before you can use it, you must
|
||||
clean up the structure when you are done with it. This is performed
|
||||
using the mp_clear() function. Remember that any mp_int that you
|
||||
create as a local variable in a function must be mp_clear()'d before
|
||||
that function exits, or else the memory allocated to that mp_int will
|
||||
be orphaned and unrecoverable.
|
||||
|
||||
To set an mp_int to a given value, the following functions are given:
|
||||
|
||||
mp_set(mp_int *mp, mp_digit d);
|
||||
mp_set_int(mp_int *mp, long z);
|
||||
|
||||
The mp_set() function sets the mp_int to a single digit value, while
|
||||
mp_set_int() sets the mp_int to a signed long integer value.
|
||||
|
||||
To set an mp_int to zero, use:
|
||||
|
||||
mp_zero(mp_int *mp);
|
||||
|
||||
|
||||
Copying and Moving
|
||||
------------------
|
||||
|
||||
If you have two initialized mp_int's, and you want to copy the value
|
||||
of one into the other, use:
|
||||
|
||||
mp_copy(from, to)
|
||||
|
||||
This takes care of clearing the old value of 'to', and copies the new
|
||||
value into it. If 'to' is not yet initialized, use mp_init_copy()
|
||||
instead (see above).
|
||||
|
||||
Note: The library tries, whenever possible, to avoid allocating
|
||||
---- new memory. Thus, mp_copy() tries first to satisfy the needs
|
||||
of the copy by re-using the memory already allocated to 'to'.
|
||||
Only if this proves insufficient will mp_copy() actually
|
||||
allocate new memory.
|
||||
|
||||
For this reason, if you know a priori that 'to' has enough
|
||||
available space to hold 'from', you don't need to check the
|
||||
return value of mp_copy() for memory failure. The USED()
|
||||
macro tells you how many digits are used by an mp_int, and
|
||||
the ALLOC() macro tells you how many are allocated.
|
||||
|
||||
If you have two initialized mp_int's, and you want to exchange their
|
||||
values, use:
|
||||
|
||||
mp_exch(a, b)
|
||||
|
||||
This is better than using mp_copy() with a temporary, since it will
|
||||
not (ever) touch the memory allocator -- it just swaps the exact
|
||||
contents of the two structures. The mp_exch() function cannot fail;
|
||||
if you pass it an invalid structure, it just ignores it, and does
|
||||
nothing.
|
||||
|
||||
|
||||
Basic Arithmetic
|
||||
----------------
|
||||
|
||||
Once you have initialized your integers, you can operate on them. The
|
||||
basic arithmetic functions on full mp_int values are:
|
||||
|
||||
mp_add(a, b, c) - computes c = a + b
|
||||
mp_sub(a, b, c) - computes c = a - b
|
||||
mp_mul(a, b, c) - computes c = a * b
|
||||
mp_sqr(a, b) - computes b = a * a
|
||||
mp_div(a, b, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2d(a, d, q, r) - computes q = a / 2^d, r = a % 2^d
|
||||
mp_expt(a, b, c) - computes c = a ** b
|
||||
mp_2expt(a, k) - computes a = 2^k
|
||||
mp_sqrt(a, c) - computes c = floor(sqrt(a))
|
||||
|
||||
The mp_div_2d() function efficiently computes division by powers of
|
||||
two. Either the q or r parameter may be NULL, in which case that
|
||||
portion of the computation will be discarded.
|
||||
|
||||
The algorithms used for some of the computations here are described in
|
||||
the following files which are included with this distribution:
|
||||
|
||||
mul.txt Describes the multiplication algorithm
|
||||
div.txt Describes the division algorithm
|
||||
expt.txt Describes the exponentiation algorithm
|
||||
sqrt.txt Describes the square-root algorithm
|
||||
square.txt Describes the squaring algorithm
|
||||
|
||||
There are single-digit versions of most of these routines, as well.
|
||||
In the following prototypes, 'd' is a single mp_digit:
|
||||
|
||||
mp_add_d(a, d, c) - computes c = a + d
|
||||
mp_sub_d(a, d, c) - computes c = a - d
|
||||
mp_mul_d(a, d, c) - computes c = a * d
|
||||
mp_mul_2(a, c) - computes c = a * 2
|
||||
mp_div_d(a, d, q, r) - computes q, r such that a = bq + r
|
||||
mp_div_2(a, c) - computes c = a / 2
|
||||
mp_expt_d(a, d, c) - computes c = a ** d
|
||||
|
||||
The mp_mul_2() and mp_div_2() functions take advantage of the internal
|
||||
representation of an mp_int to do multiplication by two more quickly
|
||||
than mp_mul_d() would. Other basic functions of an arithmetic variety
|
||||
include:
|
||||
|
||||
mp_zero(a) - assign 0 to a
|
||||
mp_neg(a, c) - negate a: c = -a
|
||||
mp_abs(a, c) - absolute value: c = |a|
|
||||
|
||||
|
||||
Comparisons
|
||||
-----------
|
||||
|
||||
Several comparison functions are provided. Each of these, unless
|
||||
otherwise specified, returns zero if the comparands are equal, < 0 if
|
||||
the first is less than the second, and > 0 if the first is greater
|
||||
than the second:
|
||||
|
||||
mp_cmp_z(a) - compare a <=> 0
|
||||
mp_cmp_d(a, d) - compare a <=> d, d is a single digit
|
||||
mp_cmp(a, b) - compare a <=> b
|
||||
mp_cmp_mag(a, b) - compare |a| <=> |b|
|
||||
mp_cmp_int(a, z) - compare a <=> z, z is a signed long integer
|
||||
mp_isodd(a) - return nonzero if odd, zero otherwise
|
||||
mp_iseven(a) - return nonzero if even, zero otherwise
|
||||
|
||||
|
||||
Modular Arithmetic
|
||||
------------------
|
||||
|
||||
Modular variations of the basic arithmetic functions are also
|
||||
supported. These are available if the MP_MODARITH parameter in
|
||||
mpi-config.h is turned on (it is by default). The modular arithmetic
|
||||
functions are:
|
||||
|
||||
mp_mod(a, m, c) - compute c = a (mod m), 0 <= c < m
|
||||
mp_mod_d(a, d, c) - compute c = a (mod d), 0 <= c < d (see below)
|
||||
mp_addmod(a, b, m, c) - compute c = (a + b) mod m
|
||||
mp_submod(a, b, m, c) - compute c = (a - b) mod m
|
||||
mp_mulmod(a, b, m, c) - compute c = (a * b) mod m
|
||||
mp_sqrmod(a, m, c) - compute c = (a * a) mod m
|
||||
mp_exptmod(a, b, m, c) - compute c = (a ** b) mod m
|
||||
mp_exptmod_d(a, d, m, c)- compute c = (a ** d) mod m
|
||||
|
||||
The mp_sqr() function squares its input argument. A call to mp_sqr(a,
|
||||
c) is identical in meaning to mp_mul(a, a, c); however, if the
|
||||
MP_SQUARE variable is set true in mpi-config.h (see below), then it
|
||||
will be implemented with a different algorithm, that is supposed to
|
||||
take advantage of the redundant computation that takes place during
|
||||
squaring. Unfortunately, some compilers result in worse performance
|
||||
on this code, so you can change the behaviour at will. There is a
|
||||
utility program "mulsqr.c" that lets you test which does better on
|
||||
your system.
|
||||
|
||||
The mp_sqrmod() function is analogous to the mp_sqr() function; it
|
||||
uses the mp_sqr() function rather than mp_mul(), and then performs the
|
||||
modular reduction. This probably won't help much unless you are doing
|
||||
a lot of them.
|
||||
|
||||
See the file 'square.txt' for a synopsis of the algorithm used.
|
||||
|
||||
Note: The mp_mod_d() function computes a modular reduction around
|
||||
---- a single digit d. The result is a single digit c.
|
||||
|
||||
Because an inverse is defined for a (mod m) if and only if (a, m) = 1
|
||||
(that is, if a and m are relatively prime), mp_invmod() may not be
|
||||
able to compute an inverse for the arguments. In this case, it
|
||||
returns the value MP_UNDEF, and does not modify c. If an inverse is
|
||||
defined, however, it returns MP_OKAY, and sets c to the value of the
|
||||
inverse (mod m).
|
||||
|
||||
See the file 'redux.txt' for a description of the modular reduction
|
||||
algorithm used by mp_exptmod().
|
||||
|
||||
|
||||
Greatest Common Divisor
|
||||
-----------------------
|
||||
|
||||
If The greates common divisor of two values can be found using one of the
|
||||
following functions:
|
||||
|
||||
mp_gcd(a, b, c) - compute c = (a, b) using binary algorithm
|
||||
mp_lcm(a, b, c) - compute c = [a, b] = ab / (a, b)
|
||||
mp_xgcd(a, b, g, x, y) - compute g, x, y so that ax + by = g = (a, b)
|
||||
|
||||
Also provided is a function to compute modular inverses, if they
|
||||
exist:
|
||||
|
||||
mp_invmod(a, m, c) - compute c = a^-1 (mod m), if it exists
|
||||
|
||||
The function mp_xgcd() computes the greatest common divisor, and also
|
||||
returns values of x and y satisfying Bezout's identity. This is used
|
||||
by mp_invmod() to find modular inverses. However, if you do not need
|
||||
these values, you will find that mp_gcd() is MUCH more efficient,
|
||||
since it doesn't need all the intermediate values that mp_xgcd()
|
||||
requires in order to compute x and y.
|
||||
|
||||
The mp_gcd() (and mp_xgcd()) functions use the binary (extended) GCD
|
||||
algorithm due to Josef Stein.
|
||||
|
||||
|
||||
Input & Output Functions
|
||||
------------------------
|
||||
|
||||
The following basic I/O routines are provided. These are present at
|
||||
all times:
|
||||
|
||||
mp_read_radix(mp, str, r) - convert a string in radix r to an mp_int
|
||||
mp_read_raw(mp, s, len) - convert a string of bytes to an mp_int
|
||||
mp_radix_size(mp, r) - return length of buffer needed by mp_toradix()
|
||||
mp_raw_size(mp) - return length of buffer needed by mp_toraw()
|
||||
mp_toradix(mp, str, r) - convert an mp_int to a string of radix r
|
||||
digits
|
||||
mp_toraw(mp, str) - convert an mp_int to a string of bytes
|
||||
mp_tovalue(ch, r) - convert ch to its value when taken as
|
||||
a radix r digit, or -1 if invalid
|
||||
mp_strerror(err) - get a string describing mp_err value 'err'
|
||||
|
||||
If you compile the MPI library with MP_IOFUNC defined, you will also
|
||||
have access to the following additional I/O function:
|
||||
|
||||
mp_print(mp, ofp) - print an mp_int as text to output stream ofp
|
||||
|
||||
Note that mp_radix_size() returns a size in bytes guaranteed to be AT
|
||||
LEAST big enough for the digits output by mp_toradix(). Because it
|
||||
uses an approximation technique to figure out how many digits will be
|
||||
needed, it may return a figure which is larger than necessary. Thus,
|
||||
the caller should not rely on the value to determine how many bytes
|
||||
will actually be written by mp_toradix(). The string mp_toradix()
|
||||
creates will be NUL terminated, so the standard C library function
|
||||
strlen() should be able to ascertain this for you, if you need it.
|
||||
|
||||
The mp_read_radix() and mp_toradix() functions support bases from 2 to
|
||||
64 inclusive. If you require more general radix conversion facilities
|
||||
than this, you will need to write them yourself (that's why mp_div_d()
|
||||
is provided, after all).
|
||||
|
||||
Note: mp_read_radix() will accept as digits either capital or
|
||||
---- lower-case letters. However, the current implementation of
|
||||
mp_toradix() only outputs upper-case letters, when writing
|
||||
bases betwee 10 and 36. The underlying code supports using
|
||||
lower-case letters, but the interface stub does not have a
|
||||
selector for it. You can add one yourself if you think it
|
||||
is worthwhile -- I do not. Bases from 36 to 64 use lower-
|
||||
case letters as distinct from upper-case. Bases 63 and
|
||||
64 use the characters '+' and '/' as digits.
|
||||
|
||||
Note also that compiling with MP_IOFUNC defined will cause
|
||||
inclusion of <stdio.h>, so if you are trying to write code
|
||||
which does not depend on the standard C library, you will
|
||||
probably want to avoid this option. This is needed because
|
||||
the mp_print() function takes a standard library FILE * as
|
||||
one of its parameters, and uses the fprintf() function.
|
||||
|
||||
The mp_toraw() function converts the integer to a sequence of bytes,
|
||||
in big-endian ordering (most-significant byte first). Assuming your
|
||||
bytes are 8 bits wide, this corresponds to base 256. The sign is
|
||||
encoded as a single leading byte, whose value is 0 for zero or
|
||||
positive values, or 1 for negative values. The mp_read_raw() function
|
||||
reverses this process -- it takes a buffer of bytes, interprets the
|
||||
first as a sign indicator (0 = zero/positive, nonzero = negative), and
|
||||
the rest as a sequence of 1-byte digits in big-endian ordering.
|
||||
|
||||
The mp_raw_size() function returns the exact number of bytes required
|
||||
to store the given integer in "raw" format (as described in the
|
||||
previous paragraph). Zero is returned in case of error; a valid
|
||||
integer will require at least three bytes of storage.
|
||||
|
||||
In previous versions of the MPI library, an "external representation
|
||||
format" was supported. This was removed, however, because I found I
|
||||
was never using it, it was not as portable as I would have liked, and
|
||||
I decided it was a waste of space.
|
||||
|
||||
|
||||
Other Functions
|
||||
---------------
|
||||
|
||||
The files 'mpprime.h' and 'mpprime.c' define some routines which are
|
||||
useful for divisibility testing and probabilistic primality testing.
|
||||
The routines defined are:
|
||||
|
||||
mpp_divis(a, b) - is a divisible by b?
|
||||
mpp_divis_d(a, d) - is a divisible by digit d?
|
||||
mpp_random(a) - set a to random value at current precision
|
||||
mpp_random_size(a, prec) - set a to random value at given precision
|
||||
|
||||
Note: The mpp_random() and mpp_random_size() functions use the C
|
||||
---- library's rand() function to generate random values. It is
|
||||
up to the caller to seed this generator before it is called.
|
||||
These functions are not suitable for generating quantities
|
||||
requiring cryptographic-quality randomness; they are intended
|
||||
primarily for use in primality testing.
|
||||
|
||||
Note too that the MPI library does not call srand(), so your
|
||||
application should do this, if you ever want the sequence
|
||||
to change.
|
||||
|
||||
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s digits
|
||||
in v? If so, let w be the index of
|
||||
that digit
|
||||
|
||||
mpp_divis_primes(a, np) - is a divisible by any of the first np
|
||||
primes? If so, set np to the prime
|
||||
which divided a.
|
||||
|
||||
mpp_fermat(a, d) - test if w^a = w (mod a). If so,
|
||||
returns MP_YES, otherwise MP_NO.
|
||||
|
||||
mpp_pprime(a, nt) - perform nt iterations of the Rabin-
|
||||
Miller probabilistic primality test
|
||||
on a. Returns MP_YES if all tests
|
||||
passed, or MP_NO if any test fails.
|
||||
|
||||
The mpp_fermat() function works based on Fermat's little theorem, a
|
||||
consequence of which is that if p is a prime, and (w, p) = 1, then:
|
||||
|
||||
w^p = w (mod p)
|
||||
|
||||
Put another way, if w^p != w (mod p), then p is not prime. The test
|
||||
is expensive to compute, but it helps to quickly eliminate an enormous
|
||||
class of composite numbers prior to Rabin-Miller testing.
|
||||
|
||||
Building the Library
|
||||
--------------------
|
||||
|
||||
The MPI library is designed to be as self-contained as possible. You
|
||||
should be able to compile it with your favourite ANSI C compiler, and
|
||||
link it into your program directly. If you are on a Unix system using
|
||||
the GNU C compiler (gcc), the following should work:
|
||||
|
||||
% gcc -ansi -pedantic -Wall -O2 -c mpi.c
|
||||
|
||||
The file 'mpi-config.h' defines several configurable parameters for
|
||||
the library, which you can adjust to suit your application. At the
|
||||
time of this writing, the available options are:
|
||||
|
||||
MP_IOFUNC - Define true to include the mp_print() function,
|
||||
which is moderately useful for debugging. This
|
||||
implicitly includes <stdio.h>.
|
||||
|
||||
MP_MODARITH - Define true to include the modular arithmetic
|
||||
functions. If you don't need modular arithmetic
|
||||
in your application, you can set this to zero to
|
||||
leave out all the modular routines.
|
||||
|
||||
MP_NUMTH - Define true to include number theoretic functions
|
||||
such as mp_gcd(), mp_lcm(), and mp_invmod().
|
||||
|
||||
MP_LOGTAB - If true, the file "logtab.h" is included, which
|
||||
is basically a static table of base 2 logarithms.
|
||||
These are used to compute how big the buffers for
|
||||
radix conversion need to be. If you set this false,
|
||||
the library includes <math.h> and uses log(). This
|
||||
typically forces you to link against math libraries.
|
||||
|
||||
MP_MEMSET - If true, use memset() to zero buffers. If you run
|
||||
into weird alignment related bugs, set this to zero
|
||||
and an explicit loop will be used.
|
||||
|
||||
MP_MEMCPY - If true, use memcpy() to copy buffers. If you run
|
||||
into weird alignment bugs, set this to zero and an
|
||||
explicit loop will be used.
|
||||
|
||||
MP_CRYPTO - If true, whenever arrays of digits are free'd, they
|
||||
are zeroed first. This is useful if you're using
|
||||
the library in a cryptographic environment; however,
|
||||
it does add overhead to each free operation. For
|
||||
performance, if you don't care about zeroing your
|
||||
buffers, set this to false.
|
||||
|
||||
MP_ARGCHK - Set to 0, 1, or 2. This defines how the argument
|
||||
checking macro, ARGCHK(), gets expanded. If this
|
||||
is set to zero, ARGCHK() expands to nothing; no
|
||||
argument checks are performed. If this is 1, the
|
||||
ARGCHK() macro expands to code that returns MP_BADARG
|
||||
or similar at runtime. If it is 2, ARGCHK() expands
|
||||
to an assert() call that aborts the program on a
|
||||
bad input.
|
||||
|
||||
MP_DEBUG - Turns on debugging output. This is probably not at
|
||||
all useful unless you are debugging the library. It
|
||||
tends to spit out a LOT of output.
|
||||
|
||||
MP_DEFPREC - The default precision of a newly-created mp_int, in
|
||||
digits. The precision can be changed at runtime by
|
||||
the mp_set_prec() function, but this is its initial
|
||||
value.
|
||||
|
||||
MP_SQUARE - If this is set to a nonzero value, the mp_sqr()
|
||||
function will use an alternate algorithm that takes
|
||||
advantage of the redundant inner product computation
|
||||
when both multiplicands are identical. Unfortunately,
|
||||
with some compilers this is actually SLOWER than just
|
||||
calling mp_mul() with the same argument twice. So
|
||||
if you set MP_SQUARE to zero, mp_sqr() will be expan-
|
||||
ded into a call to mp_mul(). This applies to all
|
||||
the uses of mp_sqr(), including mp_sqrmod() and the
|
||||
internal calls to s_mp_sqr() inside mpi.c
|
||||
|
||||
The program 'mulsqr' (mulsqr.c) can be used to test
|
||||
which works best for your configuration. Set up the
|
||||
CC and CFLAGS variables in the Makefile, then type:
|
||||
|
||||
make mulsqr
|
||||
|
||||
Invoke it with arguments similar to the following:
|
||||
|
||||
mulsqr 25000 1024
|
||||
|
||||
That is, 25000 products computed on 1024-bit values.
|
||||
The output will compare the two timings, and recommend
|
||||
a setting for MP_SQUARE. It is off by default.
|
||||
|
||||
If you would like to use the mp_print() function (see above), be sure
|
||||
to define MP_IOFUNC in mpi-config.h. Many of the test drivers in the
|
||||
'tests' subdirectory expect this to be defined (although the test
|
||||
driver 'mpi-test' doesn't need it)
|
||||
|
||||
The Makefile which comes with the library should take care of building
|
||||
the library for you, if you have set the CC and CFLAGS variables at
|
||||
the top of the file appropriately. By default, they are set up to
|
||||
use the GNU C compiler:
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-ansi -pedantic -Wall -O2
|
||||
|
||||
If all goes well, the library should compile without warnings using
|
||||
this combination. You should, of course, make whatever adjustments
|
||||
you find necessary.
|
||||
|
||||
The MPI library distribution comes with several additional programs
|
||||
which are intended to demonstrate the use of the library, and provide
|
||||
a framework for testing it. There are a handful of test driver
|
||||
programs, in the files named 'mptest-X.c', where X is a digit. Also,
|
||||
there are some simple command-line utilities (in the 'utils'
|
||||
directory) for manipulating large numbers. These include:
|
||||
|
||||
basecvt.c A radix-conversion program, supporting bases from
|
||||
2 to 64 inclusive.
|
||||
|
||||
bbsrand.c A BBS (quadratic residue) pseudo-random number
|
||||
generator. The file 'bbsrand.c' is just the driver
|
||||
for the program; the real code lives in the files
|
||||
'bbs_rand.h' and 'bbs_rand.c'
|
||||
|
||||
dec2hex.c Converts decimal to hexadecimal
|
||||
|
||||
gcd.c Computes the greatest common divisor of two values.
|
||||
If invoked as 'xgcd', also computes constants x and
|
||||
y such that (a, b) = ax + by, in accordance with
|
||||
Bezout's identity.
|
||||
|
||||
hex2dec.c Converts hexadecimal to decimal
|
||||
|
||||
invmod.c Computes modular inverses
|
||||
|
||||
isprime.c Performs the Rabin-Miller probabilistic primality
|
||||
test on a number. Values which fail this test are
|
||||
definitely composite, and those which pass are very
|
||||
likely to be prime (although there are no guarantees)
|
||||
|
||||
lap.c Computes the order (least annihilating power) of
|
||||
a value v modulo m. Very dumb algorithm.
|
||||
|
||||
primegen.c Generates large (probable) primes.
|
||||
|
||||
prng.c A pseudo-random number generator based on the
|
||||
BBS generator code in 'bbs_rand.c'
|
||||
|
||||
sieve.c Implements the Sieve of Eratosthenes, using a big
|
||||
bitmap, to generate a list of prime numbers.
|
||||
|
||||
fact.c Computes the factorial of an arbitrary precision
|
||||
integer (iterative).
|
||||
|
||||
exptmod.c Computes arbitrary precision modular exponentiation
|
||||
from the command line (exptmod a b m -> a^b (mod m))
|
||||
|
||||
Most of these can be built from the Makefile that comes with the
|
||||
library. Try 'make tools', if your environment supports it. (If you
|
||||
are compiling on a Macintosh, I'm afraid you'll have to build them by
|
||||
hand -- fortunately, this is not difficult -- the library itself
|
||||
should compile just fine under Metrowerks CodeWarrior).
|
||||
|
||||
|
||||
Testing the Library
|
||||
-------------------
|
||||
|
||||
Automatic test vectors are included, in the form of a program called
|
||||
'mpi-test'. To build this program and run all the tests, simply
|
||||
invoke the shell script 'all-tests'. If all the tests pass, you
|
||||
should see a message:
|
||||
|
||||
All tests passed
|
||||
|
||||
If something went wrong, you'll get:
|
||||
|
||||
One or more tests failed.
|
||||
|
||||
If this happens, scan back through the preceding lines, to see which
|
||||
test failed. Any failure indicates a bug in the library, which needs
|
||||
to be fixed before it will give accurate results. If you get any such
|
||||
thing, please let me know, and I'll try to fix it. Please let me know
|
||||
what platform and compiler you were using, as well as which test
|
||||
failed. If a reason for failure was given, please send me that text
|
||||
as well.
|
||||
|
||||
If you're on a system such as the Macintosh, where the standard Unix
|
||||
build tools don't work, you can build the 'mpi-test' program manually,
|
||||
and run it by hand. This is tedious and obnoxious, sorry.
|
||||
|
||||
Further manual testing can be performed by building the manual testing
|
||||
programs, whose source is found in the 'tests' subdirectory. Each
|
||||
test is in a source file called 'mptest-X.c'. The Makefile contains a
|
||||
target to build all of them at once:
|
||||
|
||||
make tests
|
||||
|
||||
Read the comments at the top of each source file to see what the
|
||||
driver is supposed to test. You probably don't need to do this; these
|
||||
programs were only written to help me as I was developing the library.
|
||||
|
||||
The relevant files are:
|
||||
|
||||
mpi-test.c The source for the test driver
|
||||
|
||||
make-test-arrays A Perl script to generate some of the internal
|
||||
data structures used by mpi-test.c
|
||||
|
||||
test-arrays.txt The source file for make-test-arrays
|
||||
|
||||
all-tests A Bourne shell script which runs all the
|
||||
tests in the mpi-test suite
|
||||
|
||||
Running 'make mpi-test' should build the mpi-test program. If you
|
||||
cannot use make, here is what needs to be done:
|
||||
|
||||
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
|
||||
the 'test-arrays.txt' file. Since Perl can be found everywhere,
|
||||
even on the Macintosh, this should be no trouble. Under Unix,
|
||||
this looks like:
|
||||
|
||||
make-test-arrays test-arrays.txt > test-info.c
|
||||
|
||||
(2) Build the MPI library:
|
||||
|
||||
gcc -ansi -pedantic -Wall -c mpi.c
|
||||
|
||||
(3) Build the mpi-test program:
|
||||
|
||||
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
|
||||
|
||||
When you've got mpi-test, you can use 'all-tests' to run all the tests
|
||||
made available by mpi-test. If any of them fail, there should be a
|
||||
diagnostic indicating what went wrong. These are fairly high-level
|
||||
diagnostics, and won't really help you debug the problem; they're
|
||||
simply intended to help you isolate which function caused the problem.
|
||||
If you encounter a problem of this sort, feel free to e-mail me, and I
|
||||
will certainly attempt to help you debug it.
|
||||
|
||||
Note: Several of the tests hard-wired into 'mpi-test' operate under
|
||||
---- the assumption that you are using at least a 16-bit mp_digit
|
||||
type. If that is not true, several tests might fail, because
|
||||
of range problems with the maximum digit value.
|
||||
|
||||
If you are using an 8-bit digit, you will also need to
|
||||
modify the code for mp_read_raw(), which assumes that
|
||||
multiplication by 256 can be done with mp_mul_d(), a
|
||||
fact that fails when DIGIT_MAX is 255. You can replace
|
||||
the call with s_mp_lshd(), which will give you the same
|
||||
effect, and without doing as much work. :)
|
||||
|
||||
Acknowledgements:
|
||||
----------------
|
||||
|
||||
The algorithms used in this library were drawn primarily from Volume
|
||||
2 of Donald Knuth's magnum opus, _The Art of Computer Programming_,
|
||||
"Semi-Numerical Methods". Barrett's algorithm for modular reduction
|
||||
came from Menezes, Oorschot, and Vanstone's _Handbook of Applied
|
||||
Cryptography_, Chapter 14.
|
||||
|
||||
Thanks are due to Tom St. Denis, for finding an obnoxious sign-related
|
||||
bug in mp_read_raw() that made things break on platforms which use
|
||||
signed chars.
|
||||
|
||||
About the Author
|
||||
----------------
|
||||
|
||||
This software was written by Michael J. Fromberger. You can contact
|
||||
the author as follows:
|
||||
|
||||
E-mail: <sting@linguist.dartmouth.edu>
|
||||
|
||||
Postal: 8000 Cummings Hall, Thayer School of Engineering
|
||||
Dartmouth College, Hanover, New Hampshire, USA
|
||||
|
||||
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
|
||||
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907
|
||||
|
||||
Last updated: 16-Jan-2000
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1997
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
ECHO=/bin/echo
|
||||
MAKE=gmake
|
||||
|
||||
$ECHO "\n** Running unit tests for MPI library\n"
|
||||
|
||||
# Build the mpi-test program, which comprises all the unit tests for
|
||||
# the MPI library...
|
||||
|
||||
$ECHO "Bringing mpi-test up to date ... "
|
||||
if $MAKE mpi-test ; then
|
||||
:
|
||||
else
|
||||
$ECHO " "
|
||||
$ECHO "Make failed to build mpi-test."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x mpi-test ] ; then
|
||||
$ECHO " "
|
||||
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
|
||||
$ECHO " "
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the list of available test suites...
|
||||
tests=`mpi-test list | awk '{print $1}'`
|
||||
errs=0
|
||||
|
||||
# Run each test suite and check the result code of mpi-test
|
||||
for test in $tests ; do
|
||||
$ECHO "$test ... \c"
|
||||
if mpi-test $test ; then
|
||||
$ECHO "passed"
|
||||
else
|
||||
$ECHO "FAILED"
|
||||
errs=1
|
||||
fi
|
||||
done
|
||||
|
||||
# If any tests failed, we'll stop at this point
|
||||
if [ "$errs" = "0" ] ; then
|
||||
$ECHO "All unit tests passed"
|
||||
else
|
||||
$ECHO "One or more tests failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now try to build the 'pi' program, and see if it can compute the
|
||||
# first thousand digits of pi correctly
|
||||
$ECHO "\n** Running other tests\n"
|
||||
|
||||
$ECHO "Bringing 'pi' up to date ... "
|
||||
if $MAKE pi ; then
|
||||
:
|
||||
else
|
||||
$ECHO "\nMake failed to build pi.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -x pi ] ; then
|
||||
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./pi 2000 > /tmp/pi.tmp.$$
|
||||
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
|
||||
$ECHO "Okay! The pi test passes."
|
||||
else
|
||||
$ECHO "Oops! The pi test failed. :("
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f /tmp/pi.tmp.$$
|
||||
|
||||
exit 0
|
||||
|
||||
# Here there be dragons
|
||||
@@ -1,11 +0,0 @@
|
||||
Within this directory, each of the file listed below is licensed under
|
||||
the terms given in the file LICENSE-MPL, also in this directory.
|
||||
|
||||
basecvt.pod
|
||||
gcd.pod
|
||||
invmod.pod
|
||||
isprime.pod
|
||||
lap.pod
|
||||
mpi-test.pod
|
||||
prime.txt
|
||||
prng.pod
|
||||
@@ -1,35 +0,0 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the Netscape security libraries.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
@@ -1,63 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
basecvt - radix conversion for arbitrary precision integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
basecvt <ibase> <obase> [values]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<basecvt> program is a command-line tool for converting integers
|
||||
of arbitrary precision from one radix to another. The current version
|
||||
supports radix values from 2 (binary) to 64, inclusive. The first two
|
||||
command line arguments specify the input and output radix, in base 10.
|
||||
Any further arguments are taken to be integers notated in the input
|
||||
radix, and these are converted to the output radix. The output is
|
||||
written, one integer per line, to standard output.
|
||||
|
||||
When reading integers, only digits considered "valid" for the input
|
||||
radix are considered. Processing of an integer terminates when an
|
||||
invalid input digit is encountered. So, for example, if you set the
|
||||
input radix to 10 and enter '10ACF', B<basecvt> would assume that you
|
||||
had entered '10' and ignore the rest of the string.
|
||||
|
||||
If no values are provided, no output is written, but the program
|
||||
simply terminates with a zero exit status. Error diagnostics are
|
||||
written to standard error in the event of out-of-range radix
|
||||
specifications. Regardless of the actual values of the input and
|
||||
output radix, the radix arguments are taken to be in base 10 (decimal)
|
||||
notation.
|
||||
|
||||
=head1 DIGITS
|
||||
|
||||
For radices from 2-10, standard ASCII decimal digits 0-9 are used for
|
||||
both input and output. For radices from 11-36, the ASCII letters A-Z
|
||||
are also included, following the convention used in hexadecimal. In
|
||||
this range, input is accepted in either upper or lower case, although
|
||||
on output only lower-case letters are used.
|
||||
|
||||
For radices from 37-62, the output includes both upper- and lower-case
|
||||
ASCII letters, and case matters. In this range, case is distinguished
|
||||
both for input and for output values.
|
||||
|
||||
For radices 63 and 64, the characters '+' (plus) and '/' (forward
|
||||
solidus) are also used. These are derived from the MIME base64
|
||||
encoding scheme. The overall encoding is not the same as base64,
|
||||
because the ASCII digits are used for the bottom of the range, and the
|
||||
letters are shifted upward; however, the output will consist of the
|
||||
same character set.
|
||||
|
||||
This input and output behaviour is inherited from the MPI library used
|
||||
by B<basecvt>, and so is not configurable at runtime.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
dec2hex(1), hex2dec(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:31 $
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the MPI Arbitrary Precision Integer Arithmetic library.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Michael J. Fromberger <sting@linguist.dartmouth.edu>.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1998
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Netscape Communications Corporation
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# $Id: build,v 1.3 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
#
|
||||
|
||||
VERS="1.7p6"
|
||||
SECT="1"
|
||||
NAME="MPI Tools"
|
||||
|
||||
echo "Building manual pages ..."
|
||||
case $# in
|
||||
0)
|
||||
files=`ls *.pod`
|
||||
;;
|
||||
*)
|
||||
files=$*
|
||||
;;
|
||||
esac
|
||||
|
||||
for name in $files
|
||||
do
|
||||
echo -n "$name ... "
|
||||
# sname=`noext $name`
|
||||
sname=`basename $name .pod`
|
||||
pod2man --section="$SECT" --center="$NAME" --release="$VERS" $name > $sname.$SECT
|
||||
echo "(done)"
|
||||
done
|
||||
|
||||
echo "Finished building."
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
Division
|
||||
|
||||
This describes the division algorithm used by the MPI library.
|
||||
|
||||
Input: a, b; a > b
|
||||
Compute: Q, R; a = Qb + R
|
||||
|
||||
The input numbers are normalized so that the high-order digit of b is
|
||||
at least half the radix. This guarantees that we have a reasonable
|
||||
way to guess at the digits of the quotient (this method was taken from
|
||||
Knuth, vol. 2, with adaptations).
|
||||
|
||||
To normalize, test the high-order digit of b. If it is less than half
|
||||
the radix, multiply both a and b by d, where:
|
||||
|
||||
radix - 1
|
||||
d = -----------
|
||||
bmax + 1
|
||||
|
||||
...where bmax is the high-order digit of b. Otherwise, set d = 1.
|
||||
|
||||
Given normalize values for a and b, let the notation a[n] denote the
|
||||
nth digit of a. Let #a be the number of significant figures of a (not
|
||||
including any leading zeroes).
|
||||
|
||||
Let R = 0
|
||||
Let p = #a - 1
|
||||
|
||||
while(p >= 0)
|
||||
do
|
||||
R = (R * radix) + a[p]
|
||||
p = p - 1
|
||||
while(R < b and p >= 0)
|
||||
|
||||
if(R < b)
|
||||
break
|
||||
|
||||
q = (R[#R - 1] * radix) + R[#R - 2]
|
||||
q = q / b[#b - 1]
|
||||
|
||||
T = b * q
|
||||
|
||||
while(T > L)
|
||||
q = q - 1
|
||||
T = T - b
|
||||
endwhile
|
||||
|
||||
L = L - T
|
||||
|
||||
Q = (Q * radix) + q
|
||||
|
||||
endwhile
|
||||
|
||||
At this point, Q is the quotient, and R is the normalized remainder.
|
||||
To denormalize R, compute:
|
||||
|
||||
R = (R / d)
|
||||
|
||||
At this point, you are finished.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: div.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
Exponentiation
|
||||
|
||||
For exponentiation, the MPI library uses a simple and fairly standard
|
||||
square-and-multiply method. The algorithm is this:
|
||||
|
||||
Input: a, b
|
||||
Output: a ** b
|
||||
|
||||
s = 1
|
||||
|
||||
while(b != 0)
|
||||
if(b is odd)
|
||||
s = s * a
|
||||
endif
|
||||
|
||||
b = b / 2
|
||||
|
||||
x = x * x
|
||||
endwhile
|
||||
|
||||
return s
|
||||
|
||||
The modular exponentiation is done the same way, except replacing:
|
||||
|
||||
s = s * a
|
||||
|
||||
with
|
||||
s = (s * a) mod m
|
||||
|
||||
and replacing
|
||||
|
||||
x = x * x
|
||||
|
||||
with
|
||||
|
||||
x = (x * x) mod m
|
||||
|
||||
Here is a sample exponentiation using the MPI library, as compared to
|
||||
the same problem solved by the Unix 'bc' program on my system:
|
||||
|
||||
Computation of 2,381,283 ** 235
|
||||
|
||||
'bc' says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
MPI says:
|
||||
|
||||
4385CA4A804D199FBEAD95FAD0796FAD0D0B51FC9C16743C45568C789666985DB719\
|
||||
4D90E393522F74C9601262C0514145A49F3B53D00983F95FDFCEA3D0043ECEF6227E\
|
||||
6FB59C924C3EE74447B359B5BF12A555D46CB819809EF423F004B55C587D6F0E8A55\
|
||||
4988036A42ACEF9F71459F97CEF6E574BD7373657111648626B1FF8EE15F663B2C0E\
|
||||
6BBE5082D4CDE8E14F263635AE8F35DB2C280819517BE388B5573B84C5A19C871685\
|
||||
FD408A6471F9D6AFAF5129A7548EAE926B40874B340285F44765BF5468CE20A13267\
|
||||
CD88CE6BC786ACED36EC7EA50F67FF27622575319068A332C3C0CB23E26FB55E26F4\
|
||||
5F732753A52B8E2FB4D4F42D894242613CA912A25486C3DEC9C66E5DB6182F6C1761\
|
||||
CF8CD0D255BE64B93836B27D452AE38F950EB98B517D4CF50D48F0165EF0CCCE1F5C\
|
||||
49BF18219FDBA0EEDD1A7E8B187B70C2BAED5EC5C6821EF27FAFB1CFF70111C52235\
|
||||
5E948B93A015AA1AE152B110BB5658CB14D3E45A48BFE7F082C1182672A455A695CD\
|
||||
A1855E8781E625F25B41B516E77F589FA420C3B058861EA138CF7A2C58DB3C7504FD\
|
||||
D29554D78237834CC5AE710D403CC4F6973D5012B7E117A8976B14A0B5AFA889BD47\
|
||||
92C461F0F96116F00A97AE9E83DC5203680CAF9A18A062566C145650AB86BE4F907F\
|
||||
A9F7AB4A700B29E1E5BACCD6DCBFA513E10832815F710807EED2E279081FEC61D619\
|
||||
AB270BEB3D3A1787B35A9DD41A8766CF21F3B5C693B3BAB1C2FA14A4ED202BC35743\
|
||||
E5CBE2391624D4F8C9BFBBC78D69764E7C6C5B11BF005677BFAD17D9278FFC1F158F\
|
||||
1B3683FF7960FA0608103792C4163DC0AF3E06287BB8624F8FE3A0FFBDF82ACECA2F\
|
||||
CFFF2E1AC93F3CA264A1B
|
||||
|
||||
Diff says:
|
||||
% diff bc.txt mp.txt
|
||||
%
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: expt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
gcd - compute greatest common divisor of two integers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
gcd <a> <b>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<gcd> program computes the greatest common divisor of two
|
||||
arbitrary-precision integers I<a> and I<b>. The result is written in
|
||||
standard decimal notation to the standard output.
|
||||
|
||||
If I<b> is zero, B<gcd> will print an error message and exit.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
invmod(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:32 $
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
invmod - compute modular inverse of an integer
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invmod <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<invmod> program computes the inverse of I<a>, modulo I<m>, if
|
||||
that inverse exists. Both I<a> and I<m> are arbitrary-precision
|
||||
integers in decimal notation. The result is written in standard
|
||||
decimal notation to the standard output.
|
||||
|
||||
If there is no inverse, the message:
|
||||
|
||||
No inverse
|
||||
|
||||
...will be printed to the standard output (an inverse exists if and
|
||||
only if the greatest common divisor of I<a> and I<m> is 1).
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), isprime(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
isprime - probabilistic primality testing
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
isprime <a>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<isprime> program attempts to determine whether the arbitrary
|
||||
precision integer I<a> is prime. It first tests I<a> for divisibility
|
||||
by the first 170 or so small primes, and assuming I<a> is not
|
||||
divisible by any of these, applies 15 iterations of the Rabin-Miller
|
||||
probabilistic primality test.
|
||||
|
||||
If the program discovers that the number is composite, it will print:
|
||||
|
||||
Not prime (reason)
|
||||
|
||||
Where I<reason> is either:
|
||||
|
||||
divisible by small prime x
|
||||
|
||||
Or:
|
||||
|
||||
failed nth pseudoprime test
|
||||
|
||||
In the first case, I<x> indicates the first small prime factor that
|
||||
was found. In the second case, I<n> indicates which of the
|
||||
pseudoprime tests failed (numbered from 1)
|
||||
|
||||
If this happens, the number is definitely not prime. However, if the
|
||||
number succeeds, this message results:
|
||||
|
||||
Probably prime, 1 in 4^15 chance of false positive
|
||||
|
||||
If this happens, the number is prime with very high probability, but
|
||||
its primality has not been absolutely proven, only demonstrated to a
|
||||
very convincing degree.
|
||||
|
||||
The value I<a> can be input in standard decimal notation, or, if it is
|
||||
prefixed with I<Ox>, it will be read as hexadecimal.
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
You can control how many iterations of Rabin-Miller are performed on
|
||||
the candidate number by setting the I<RM_TESTS> environment variable
|
||||
to an integer value before starting up B<isprime>. This will change
|
||||
the output slightly if the number passes all the tests.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), lap(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:33 $
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
lap - compute least annihilating power of a number
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
lap <a> <m>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<lap> program computes the order of I<a> modulo I<m>, for
|
||||
arbitrary precision integers I<a> and I<m>. The B<order> of I<a>
|
||||
modulo I<m> is defined as the smallest positive value I<n> for which
|
||||
I<a> raised to the I<n>th power, modulo I<m>, is equal to 1. The
|
||||
order may not exist, if I<m> is composite.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
This program is very slow, especially for large moduli. It is
|
||||
intended as a way to help find primitive elements in a modular field,
|
||||
but it does not do so in a particularly inefficient manner. It was
|
||||
written simply to help verify that a particular candidate does not
|
||||
have an obviously short cycle mod I<m>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
gcd(1), invmod(1), isprime(1)
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
mpi-test - automated test program for MPI library
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
mpi-test <suite-name> [quiet]
|
||||
mpi-test list
|
||||
mpi-test help
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<mpi-test> program is a general unit test driver for the MPI
|
||||
library. It is used to verify that the library works as it is
|
||||
supposed to on your architecture. As with most such things, passing
|
||||
all the tests in B<mpi-test> does not guarantee the code is correct,
|
||||
but if any of them fail, there are certainly problems.
|
||||
|
||||
Each major function of the library can be tested individually. For a
|
||||
list of the test suites understood by B<mpi-test>, run it with the
|
||||
I<list> command line option:
|
||||
|
||||
mpi-test list
|
||||
|
||||
This will display a list of the available test suites and a brief
|
||||
synopsis of what each one does. For a brief overview of this
|
||||
document, run B<mpi-test> I<help>.
|
||||
|
||||
B<mpi-test> exits with a zero status if the selected test succeeds, or
|
||||
a nonzero status if it fails. If a I<suite-name> which is not
|
||||
understood by B<mpi-test> is given, a diagnostic is printed to the
|
||||
standard error, and the program exits with a result code of 2. If a
|
||||
test fails, the result code will be 1, and a diagnostic is ordinarily
|
||||
printed to the standard error. However, if the I<quiet> option is
|
||||
provided, these diagnostics will be suppressed.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
Only a few canned test cases are provided. The solutions have been
|
||||
verified using the GNU bc(1) program, so bugs there may cause problems
|
||||
here; however, this is very unlikely, so if a test fails, it is almost
|
||||
certainly my fault, not bc(1)'s.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Thayer School of Engineering, Hanover, New Hampshire, USA
|
||||
|
||||
$Date: 2000-07-14 00:44:34 $
|
||||
@@ -1,114 +0,0 @@
|
||||
Multiplication
|
||||
|
||||
This describes the multiplication algorithm used by the MPI library.
|
||||
|
||||
This is basically a standard "schoolbook" algorithm. It is slow --
|
||||
O(mn) for m = #a, n = #b -- but easy to implement and verify.
|
||||
Basically, we run two nested loops, as illustrated here (R is the
|
||||
radix):
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#b - 1)
|
||||
for i <- 0 to (#a - 1)
|
||||
w = (a[j] * b[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
It is necessary that 'w' have room for at least two radix R digits.
|
||||
The product of any two digits in radix R is at most:
|
||||
|
||||
(R - 1)(R - 1) = R^2 - 2R + 1
|
||||
|
||||
Since a two-digit radix-R number can hold R^2 - 1 distinct values,
|
||||
this insures that the product will fit into the two-digit register.
|
||||
|
||||
To insure that two digits is enough for w, we must also show that
|
||||
there is room for the carry-in from the previous multiplication, and
|
||||
the current value of the product digit that is being recomputed.
|
||||
Assuming each of these may be as big as R - 1 (and no larger,
|
||||
certainly), two digits will be enough if and only if:
|
||||
|
||||
(R^2 - 2R + 1) + 2(R - 1) <= R^2 - 1
|
||||
|
||||
Solving this equation shows that, indeed, this is the case:
|
||||
|
||||
R^2 - 2R + 1 + 2R - 2 <= R^2 - 1
|
||||
|
||||
R^2 - 1 <= R^2 - 1
|
||||
|
||||
This suggests that a good radix would be one more than the largest
|
||||
value that can be held in half a machine word -- so, for example, as
|
||||
in this implementation, where we used a radix of 65536 on a machine
|
||||
with 4-byte words. Another advantage of a radix of this sort is that
|
||||
binary-level operations are easy on numbers in this representation.
|
||||
|
||||
Here's an example multiplication worked out longhand in radix-10,
|
||||
using the above algorithm:
|
||||
|
||||
a = 999
|
||||
b = x 999
|
||||
-------------
|
||||
p = 98001
|
||||
|
||||
w = (a[jx] * b[ix]) + kin + c[ix + jx]
|
||||
c[ix+jx] = w % RADIX
|
||||
k = w / RADIX
|
||||
product
|
||||
ix jx a[jx] b[ix] kin w c[i+j] kout 000000
|
||||
0 0 9 9 0 81+0+0 1 8 000001
|
||||
0 1 9 9 8 81+8+0 9 8 000091
|
||||
0 2 9 9 8 81+8+0 9 8 000991
|
||||
8 0 008991
|
||||
1 0 9 9 0 81+0+9 0 9 008901
|
||||
1 1 9 9 9 81+9+9 9 9 008901
|
||||
1 2 9 9 9 81+9+8 8 9 008901
|
||||
9 0 098901
|
||||
2 0 9 9 0 81+0+9 0 9 098001
|
||||
2 1 9 9 9 81+9+8 8 9 098001
|
||||
2 2 9 9 9 81+9+9 9 9 098001
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: mul.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
This file describes how pi is computed by the program in 'pi.c' (see
|
||||
the utils subdirectory).
|
||||
|
||||
Basically, we use Machin's formula, which is what everyone in the
|
||||
world uses as a simple method for computing approximations to pi.
|
||||
This works for up to a few thousand digits without too much effort.
|
||||
Beyond that, though, it gets too slow.
|
||||
|
||||
Machin's formula states:
|
||||
|
||||
pi := 16 * arctan(1/5) - 4 * arctan(1/239)
|
||||
|
||||
We compute this in integer arithmetic by first multiplying everything
|
||||
through by 10^d, where 'd' is the number of digits of pi we wanted to
|
||||
compute. It turns out, the last few digits will be wrong, but the
|
||||
number that are wrong is usually very small (ordinarly only 2-3).
|
||||
Having done this, we compute the arctan() function using the formula:
|
||||
|
||||
1 1 1 1 1
|
||||
arctan(1/x) := --- - ----- + ----- - ----- + ----- - ...
|
||||
x 3 x^3 5 x^5 7 x^7 9 x^9
|
||||
|
||||
This is done iteratively by computing the first term manually, and
|
||||
then iteratively dividing x^2 and k, where k = 3, 5, 7, ... out of the
|
||||
current figure. This is then added to (or subtracted from) a running
|
||||
sum, as appropriate. The iteration continues until we overflow our
|
||||
available precision and the current figure goes to zero under integer
|
||||
division. At that point, we're finished.
|
||||
|
||||
Actually, we get a couple extra bits of precision out of the fact that
|
||||
we know we're computing y * arctan(1/x), by setting up the multiplier
|
||||
as:
|
||||
|
||||
y * 10^d
|
||||
|
||||
... instead of just 10^d. There is also a bit of cleverness in how
|
||||
the loop is constructed, to avoid special-casing the first term.
|
||||
Check out the code for arctan() in 'pi.c', if you are interested in
|
||||
seeing how it is set up.
|
||||
|
||||
Thanks to Jason P. for this algorithm, which I assembled from notes
|
||||
and programs found on his cool "Pile of Pi Programs" page, at:
|
||||
|
||||
http://www.isr.umd.edu/~jasonp/pipage.html
|
||||
|
||||
Thanks also to Henrik Johansson <Henrik.Johansson@Nexus.Comm.SE>, from
|
||||
whose pi program I borrowed the clever idea of pre-multiplying by x in
|
||||
order to avoid a special case on the loop iteration.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: pi.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
prng - pseudo-random number generator
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
prng [count]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<Prng> generates 32-bit pseudo-random integers using the
|
||||
Blum-Blum-Shub (BBS) quadratic residue generator. It is seeded using
|
||||
the standard C library's rand() function, which itself seeded from the
|
||||
system clock and the process ID number. Thus, the values generated
|
||||
are not particularly useful for cryptographic applications, but they
|
||||
are in general much better than the typical output of the usual
|
||||
multiplicative congruency generator used by most runtime libraries.
|
||||
|
||||
You may optionally specify how many random values should be generated
|
||||
by giving a I<count> argument on the command line. If you do not
|
||||
specify a count, only one random value will be generated. The results
|
||||
are output to the standard output in decimal notation, one value per
|
||||
line.
|
||||
|
||||
=head1 RESTRICTIONS
|
||||
|
||||
As stated above, B<prng> uses the C library's rand() function to seed
|
||||
the generator, so it is not terribly suitable for cryptographic
|
||||
applications. Also note that each time you run the program, a new
|
||||
seed is generated, so it is better to run it once with a I<count>
|
||||
parameter than it is to run it multiple times to generate several
|
||||
values.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
|
||||
Thayer School of Engineering, Dartmouth College, Hanover, NH USA
|
||||
|
||||
$Date: 2000-07-14 00:44:36 $
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
Modular Reduction
|
||||
|
||||
Usually, modular reduction is accomplished by long division, using the
|
||||
mp_div() or mp_mod() functions. However, when performing modular
|
||||
exponentiation, you spend a lot of time reducing by the same modulus
|
||||
again and again. For this purpose, doing a full division for each
|
||||
multiplication is quite inefficient.
|
||||
|
||||
For this reason, the mp_exptmod() function does not perform modular
|
||||
reductions in the usual way, but instead takes advantage of an
|
||||
algorithm due to Barrett, as described by Menezes, Oorschot and
|
||||
VanStone in their book _Handbook of Applied Cryptography_, published
|
||||
by the CRC Press (see Chapter 14 for details). This method reduces
|
||||
most of the computation of reduction to efficient shifting and masking
|
||||
operations, and avoids the multiple-precision division entirely.
|
||||
|
||||
Here is a brief synopsis of Barrett reduction, as it is implemented in
|
||||
this library.
|
||||
|
||||
Let b denote the radix of the computation (one more than the maximum
|
||||
value that can be denoted by an mp_digit). Let m be the modulus, and
|
||||
let k be the number of significant digits of m. Let x be the value to
|
||||
be reduced modulo m. By the Division Theorem, there exist unique
|
||||
integers Q and R such that:
|
||||
|
||||
x = Qm + R, 0 <= R < m
|
||||
|
||||
Barrett reduction takes advantage of the fact that you can easily
|
||||
approximate Q to within two, given a value M such that:
|
||||
|
||||
2k
|
||||
b
|
||||
M = floor( ----- )
|
||||
m
|
||||
|
||||
Computation of M requires a full-precision division step, so if you
|
||||
are only doing a single reduction by m, you gain no advantage.
|
||||
However, when multiple reductions by the same m are required, this
|
||||
division need only be done once, beforehand. Using this, we can use
|
||||
the following equation to compute Q', an approximation of Q:
|
||||
|
||||
x
|
||||
floor( ------ ) M
|
||||
k-1
|
||||
b
|
||||
Q' = floor( ----------------- )
|
||||
k+1
|
||||
b
|
||||
|
||||
The divisions by b^(k-1) and b^(k+1) and the floor() functions can be
|
||||
efficiently implemented with shifts and masks, leaving only a single
|
||||
multiplication to be performed to get this approximation. It can be
|
||||
shown that Q - 2 <= Q' <= Q, so in the worst case, we can get out with
|
||||
two additional subtractions to bring the value into line with the
|
||||
actual value of Q.
|
||||
|
||||
Once we've got Q', we basically multiply that by m and subtract from
|
||||
x, yielding:
|
||||
|
||||
x - Q'm = Qm + R - Q'm
|
||||
|
||||
Since we know the constraint on Q', this is one of:
|
||||
|
||||
R
|
||||
m + R
|
||||
2m + R
|
||||
|
||||
Since R < m by the Division Theorem, we can simply subtract off m
|
||||
until we get a value in the correct range, which will happen with no
|
||||
more than 2 subtractions:
|
||||
|
||||
v = x - Q'm
|
||||
|
||||
while(v >= m)
|
||||
v = v - m
|
||||
endwhile
|
||||
|
||||
|
||||
In random performance trials, modular exponentiation using this method
|
||||
of reduction gave around a 40% speedup over using the division for
|
||||
reduction.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: redux.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
@@ -1,87 +0,0 @@
|
||||
Square Root
|
||||
|
||||
A simple iterative algorithm is used to compute the greatest integer
|
||||
less than or equal to the square root. Essentially, this is Newton's
|
||||
linear approximation, computed by finding successive values of the
|
||||
equation:
|
||||
|
||||
x[k]^2 - V
|
||||
x[k+1] = x[k] - ------------
|
||||
2 x[k]
|
||||
|
||||
...where V is the value for which the square root is being sought. In
|
||||
essence, what is happening here is that we guess a value for the
|
||||
square root, then figure out how far off we were by squaring our guess
|
||||
and subtracting the target. Using this value, we compute a linear
|
||||
approximation for the error, and adjust the "guess". We keep doing
|
||||
this until the precision gets low enough that the above equation
|
||||
yields a quotient of zero. At this point, our last guess is one
|
||||
greater than the square root we're seeking.
|
||||
|
||||
The initial guess is computed by dividing V by 4, which is a heuristic
|
||||
I have found to be fairly good on average. This also has the
|
||||
advantage of being very easy to compute efficiently, even for large
|
||||
values.
|
||||
|
||||
So, the resulting algorithm works as follows:
|
||||
|
||||
x = V / 4 /* compute initial guess */
|
||||
|
||||
loop
|
||||
t = (x * x) - V /* Compute absolute error */
|
||||
u = 2 * x /* Adjust by tangent slope */
|
||||
t = t / u
|
||||
|
||||
/* Loop is done if error is zero */
|
||||
if(t == 0)
|
||||
break
|
||||
|
||||
/* Adjust guess by error term */
|
||||
x = x - t
|
||||
end
|
||||
|
||||
x = x - 1
|
||||
|
||||
The result of the computation is the value of x.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: sqrt.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
Squaring Algorithm
|
||||
|
||||
When you are squaring a value, you can take advantage of the fact that
|
||||
half the multiplications performed by the more general multiplication
|
||||
algorithm (see 'mul.txt' for a description) are redundant when the
|
||||
multiplicand equals the multiplier.
|
||||
|
||||
In particular, the modified algorithm is:
|
||||
|
||||
k = 0
|
||||
for j <- 0 to (#a - 1)
|
||||
w = c[2*j] + (a[j] ^ 2);
|
||||
k = w div R
|
||||
|
||||
for i <- j+1 to (#a - 1)
|
||||
w = (2 * a[j] * a[i]) + k + c[i+j]
|
||||
c[i+j] = w mod R
|
||||
k = w div R
|
||||
endfor
|
||||
c[i+j] = k;
|
||||
k = 0;
|
||||
endfor
|
||||
|
||||
On the surface, this looks identical to the multiplication algorithm;
|
||||
however, note the following differences:
|
||||
|
||||
- precomputation of the leading term in the outer loop
|
||||
|
||||
- i runs from j+1 instead of from zero
|
||||
|
||||
- doubling of a[i] * a[j] in the inner product
|
||||
|
||||
Unfortunately, the construction of the inner product is such that we
|
||||
need more than two digits to represent the inner product, in some
|
||||
cases. In a C implementation, this means that some gymnastics must be
|
||||
performed in order to handle overflow, for which C has no direct
|
||||
abstraction. We do this by observing the following:
|
||||
|
||||
If we have multiplied a[i] and a[j], and the product is more than half
|
||||
the maximum value expressible in two digits, then doubling this result
|
||||
will overflow into a third digit. If this occurs, we take note of the
|
||||
overflow, and double it anyway -- C integer arithmetic ignores
|
||||
overflow, so the two digits we get back should still be valid, modulo
|
||||
the overflow.
|
||||
|
||||
Having doubled this value, we now have to add in the remainders and
|
||||
the digits already computed by earlier steps. If we did not overflow
|
||||
in the previous step, we might still cause an overflow here. That
|
||||
will happen whenever the maximum value expressible in two digits, less
|
||||
the amount we have to add, is greater than the result of the previous
|
||||
step. Thus, the overflow computation is:
|
||||
|
||||
|
||||
u = 0
|
||||
w = a[i] * a[j]
|
||||
|
||||
if(w > (R - 1)/ 2)
|
||||
u = 1;
|
||||
|
||||
w = w * 2
|
||||
v = c[i + j] + k
|
||||
|
||||
if(u == 0 && (R - 1 - v) < w)
|
||||
u = 1
|
||||
|
||||
If there is an overflow, u will be 1, otherwise u will be 0. The rest
|
||||
of the parameters are the same as they are in the above description.
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: square.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
MPI Library Timing Tests
|
||||
|
||||
Hardware/OS
|
||||
(A) SGI O2 1 x MIPS R10000 250MHz IRIX 6.5.3
|
||||
(B) IBM RS/6000 43P-240 1 x PowerPC 603e 223MHz AIX 4.3
|
||||
(C) Dell GX1/L+ 1 x Pentium III 550MHz Linux 2.2.12-20
|
||||
(D) PowerBook G3 1 x PowerPC 750 266MHz LinuxPPC 2.2.6-15apmac
|
||||
(E) PowerBook G3 1 x PowerPC 750 266MHz MacOS 8.5.1
|
||||
(F) PowerBook G3 1 x PowerPC 750 400MHz MacOS 9.0.2
|
||||
|
||||
Compiler
|
||||
(1) MIPSpro C 7.2.1 -O3 optimizations
|
||||
(2) GCC 2.95.1 -O3 optimizations
|
||||
(3) IBM AIX xlc -O3 optimizations (version unknown)
|
||||
(4) EGCS 2.91.66 -O3 optimizations
|
||||
(5) Metrowerks CodeWarrior 5.0 C, all optimizations
|
||||
(6) MIPSpro C 7.30 -O3 optimizations
|
||||
(7) same as (6), with optimized libmalloc.so
|
||||
|
||||
Timings are given in seconds, computed using the C library's clock()
|
||||
function. The first column gives the hardware and compiler
|
||||
configuration used for the test. The second column indicates the
|
||||
number of tests that were aggregated to get the statistics for that
|
||||
size. These were compiled using 16 bit digits.
|
||||
|
||||
Source data were generated randomly using a fixed seed, so they should
|
||||
be internally consistent, but may vary on different systems depending
|
||||
on the C library. Also, since the resolution of the timer accessed by
|
||||
clock() varies, there may be some variance in the precision of these
|
||||
measurements.
|
||||
|
||||
Prime Generation (primegen)
|
||||
|
||||
128 bits:
|
||||
A1 200 min=0.03, avg=0.19, max=0.72, sum=38.46
|
||||
A2 200 min=0.02, avg=0.16, max=0.62, sum=32.55
|
||||
B3 200 min=0.01, avg=0.07, max=0.22, sum=13.29
|
||||
C4 200 min=0.00, avg=0.03, max=0.20, sum=6.14
|
||||
D4 200 min=0.00, avg=0.05, max=0.33, sum=9.70
|
||||
A6 200 min=0.01, avg=0.09, max=0.36, sum=17.48
|
||||
A7 200 min=0.00, avg=0.05, max=0.24, sum=10.07
|
||||
|
||||
192 bits:
|
||||
A1 200 min=0.05, avg=0.45, max=3.13, sum=89.96
|
||||
A2 200 min=0.04, avg=0.39, max=2.61, sum=77.55
|
||||
B3 200 min=0.02, avg=0.18, max=1.25, sum=36.97
|
||||
C4 200 min=0.01, avg=0.09, max=0.33, sum=18.24
|
||||
D4 200 min=0.02, avg=0.15, max=0.54, sum=29.63
|
||||
A6 200 min=0.02, avg=0.24, max=1.70, sum=47.84
|
||||
A7 200 min=0.01, avg=0.15, max=1.05, sum=30.88
|
||||
|
||||
256 bits:
|
||||
A1 200 min=0.08, avg=0.92, max=6.13, sum=184.79
|
||||
A2 200 min=0.06, avg=0.76, max=5.03, sum=151.11
|
||||
B3 200 min=0.04, avg=0.41, max=2.68, sum=82.35
|
||||
C4 200 min=0.02, avg=0.19, max=0.69, sum=37.91
|
||||
D4 200 min=0.03, avg=0.31, max=1.15, sum=63.00
|
||||
A6 200 min=0.04, avg=0.48, max=3.13, sum=95.46
|
||||
A7 200 min=0.03, avg=0.37, max=2.36, sum=73.60
|
||||
|
||||
320 bits:
|
||||
A1 200 min=0.11, avg=1.59, max=6.14, sum=318.81
|
||||
A2 200 min=0.09, avg=1.27, max=4.93, sum=254.03
|
||||
B3 200 min=0.07, avg=0.82, max=3.13, sum=163.80
|
||||
C4 200 min=0.04, avg=0.44, max=1.91, sum=87.59
|
||||
D4 200 min=0.06, avg=0.73, max=3.22, sum=146.73
|
||||
A6 200 min=0.07, avg=0.93, max=3.50, sum=185.01
|
||||
A7 200 min=0.05, avg=0.76, max=2.94, sum=151.78
|
||||
|
||||
384 bits:
|
||||
A1 200 min=0.16, avg=2.69, max=11.41, sum=537.89
|
||||
A2 200 min=0.13, avg=2.15, max=9.03, sum=429.14
|
||||
B3 200 min=0.11, avg=1.54, max=6.49, sum=307.78
|
||||
C4 200 min=0.06, avg=0.81, max=4.84, sum=161.13
|
||||
D4 200 min=0.10, avg=1.38, max=8.31, sum=276.81
|
||||
A6 200 min=0.11, avg=1.73, max=7.36, sum=345.55
|
||||
A7 200 min=0.09, avg=1.46, max=6.12, sum=292.02
|
||||
|
||||
448 bits:
|
||||
A1 200 min=0.23, avg=3.36, max=15.92, sum=672.63
|
||||
A2 200 min=0.17, avg=2.61, max=12.25, sum=522.86
|
||||
B3 200 min=0.16, avg=2.10, max=9.83, sum=420.86
|
||||
C4 200 min=0.09, avg=1.44, max=7.64, sum=288.36
|
||||
D4 200 min=0.16, avg=2.50, max=13.29, sum=500.17
|
||||
A6 200 min=0.15, avg=2.31, max=10.81, sum=461.58
|
||||
A7 200 min=0.14, avg=2.03, max=9.53, sum=405.16
|
||||
|
||||
512 bits:
|
||||
A1 200 min=0.30, avg=6.12, max=22.18, sum=1223.35
|
||||
A2 200 min=0.25, avg=4.67, max=16.90, sum=933.18
|
||||
B3 200 min=0.23, avg=4.13, max=14.94, sum=825.45
|
||||
C4 200 min=0.13, avg=2.08, max=9.75, sum=415.22
|
||||
D4 200 min=0.24, avg=4.04, max=20.18, sum=808.11
|
||||
A6 200 min=0.22, avg=4.47, max=16.19, sum=893.83
|
||||
A7 200 min=0.20, avg=4.03, max=14.65, sum=806.02
|
||||
|
||||
Modular Exponentation (metime)
|
||||
|
||||
The following results are aggregated from 200 pseudo-randomly
|
||||
generated tests, based on a fixed seed.
|
||||
|
||||
base, exponent, and modulus size (bits)
|
||||
P/C 128 192 256 320 384 448 512 640 768 896 1024
|
||||
------- -----------------------------------------------------------------
|
||||
A1 0.015 0.027 0.047 0.069 0.098 0.133 0.176 0.294 0.458 0.680 1.040
|
||||
A2 0.013 0.024 0.037 0.053 0.077 0.102 0.133 0.214 0.326 0.476 0.668
|
||||
B3 0.005 0.011 0.021 0.036 0.056 0.084 0.121 0.222 0.370 0.573 0.840
|
||||
C4 0.002 0.006 0.011 0.020 0.032 0.048 0.069 0.129 0.223 0.344 0.507
|
||||
D4 0.004 0.010 0.019 0.034 0.056 0.085 0.123 0.232 0.390 0.609 0.899
|
||||
E5 0.007 0.015 0.031 0.055 0.088 0.133 0.183 0.342 0.574 0.893 1.317
|
||||
A6 0.008 0.016 0.038 0.042 0.064 0.093 0.133 0.239 0.393 0.604 0.880
|
||||
A7 0.005 0.011 0.020 0.036 0.056 0.083 0.121 0.223 0.374 0.583 0.855
|
||||
|
||||
Multiplication and Squaring tests, (mulsqr)
|
||||
|
||||
The following results are aggregated from 500000 pseudo-randomly
|
||||
generated tests, based on a per-run wall-clock seed. Times are given
|
||||
in seconds, except where indicated in microseconds (us).
|
||||
|
||||
(A1)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 9.33 9.15 > 1.9 18.7us 18.3us
|
||||
128 10.88 10.44 > 4.0 21.8us 20.9us
|
||||
192 13.30 11.89 > 10.6 26.7us 23.8us
|
||||
256 14.88 12.64 > 15.1 29.8us 25.3us
|
||||
320 18.64 15.01 > 19.5 37.3us 30.0us
|
||||
384 23.11 17.70 > 23.4 46.2us 35.4us
|
||||
448 28.28 20.88 > 26.2 56.6us 41.8us
|
||||
512 34.09 24.51 > 28.1 68.2us 49.0us
|
||||
640 47.86 33.25 > 30.5 95.7us 66.5us
|
||||
768 64.91 43.54 > 32.9 129.8us 87.1us
|
||||
896 84.49 55.48 > 34.3 169.0us 111.0us
|
||||
1024 107.25 69.21 > 35.5 214.5us 138.4us
|
||||
1536 227.97 141.91 > 37.8 456.0us 283.8us
|
||||
2048 394.05 242.15 > 38.5 788.1us 484.3us
|
||||
|
||||
(A2)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 7.87 7.95 < 1.0 15.7us 15.9us
|
||||
128 9.40 9.19 > 2.2 18.8us 18.4us
|
||||
192 11.15 10.59 > 5.0 22.3us 21.2us
|
||||
256 12.02 11.16 > 7.2 24.0us 22.3us
|
||||
320 14.62 13.43 > 8.1 29.2us 26.9us
|
||||
384 17.72 15.80 > 10.8 35.4us 31.6us
|
||||
448 21.24 18.51 > 12.9 42.5us 37.0us
|
||||
512 25.36 21.78 > 14.1 50.7us 43.6us
|
||||
640 34.57 29.00 > 16.1 69.1us 58.0us
|
||||
768 46.10 37.60 > 18.4 92.2us 75.2us
|
||||
896 58.94 47.72 > 19.0 117.9us 95.4us
|
||||
1024 73.76 59.12 > 19.8 147.5us 118.2us
|
||||
1536 152.00 118.80 > 21.8 304.0us 237.6us
|
||||
2048 259.41 199.57 > 23.1 518.8us 399.1us
|
||||
|
||||
(B3)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 2.60 2.47 > 5.0 5.20us 4.94us
|
||||
128 4.43 4.06 > 8.4 8.86us 8.12us
|
||||
192 7.03 6.10 > 13.2 14.1us 12.2us
|
||||
256 10.44 8.59 > 17.7 20.9us 17.2us
|
||||
320 14.44 11.64 > 19.4 28.9us 23.3us
|
||||
384 19.12 15.08 > 21.1 38.2us 30.2us
|
||||
448 24.55 19.09 > 22.2 49.1us 38.2us
|
||||
512 31.03 23.53 > 24.2 62.1us 47.1us
|
||||
640 45.05 33.80 > 25.0 90.1us 67.6us
|
||||
768 63.02 46.05 > 26.9 126.0us 92.1us
|
||||
896 83.74 60.29 > 28.0 167.5us 120.6us
|
||||
1024 106.73 76.65 > 28.2 213.5us 153.3us
|
||||
1536 228.94 160.98 > 29.7 457.9us 322.0us
|
||||
2048 398.08 275.93 > 30.7 796.2us 551.9us
|
||||
|
||||
(C4)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.34 1.28 > 4.5 2.68us 2.56us
|
||||
128 2.76 2.59 > 6.2 5.52us 5.18us
|
||||
192 4.52 4.16 > 8.0 9.04us 8.32us
|
||||
256 6.64 5.99 > 9.8 13.3us 12.0us
|
||||
320 9.20 8.13 > 11.6 18.4us 16.3us
|
||||
384 12.01 10.58 > 11.9 24.0us 21.2us
|
||||
448 15.24 13.33 > 12.5 30.5us 26.7us
|
||||
512 19.02 16.46 > 13.5 38.0us 32.9us
|
||||
640 27.56 23.54 > 14.6 55.1us 47.1us
|
||||
768 37.89 31.78 > 16.1 75.8us 63.6us
|
||||
896 49.24 41.42 > 15.9 98.5us 82.8us
|
||||
1024 62.59 52.18 > 16.6 125.2us 104.3us
|
||||
1536 131.66 107.72 > 18.2 263.3us 215.4us
|
||||
2048 226.45 182.95 > 19.2 453.0us 365.9us
|
||||
|
||||
(A7)
|
||||
|
||||
bits multiply square ad percent time/mult time/square
|
||||
64 1.74 1.71 > 1.7 3.48us 3.42us
|
||||
128 3.48 2.96 > 14.9 6.96us 5.92us
|
||||
192 5.74 4.60 > 19.9 11.5us 9.20us
|
||||
256 8.75 6.61 > 24.5 17.5us 13.2us
|
||||
320 12.5 8.99 > 28.1 25.0us 18.0us
|
||||
384 16.9 11.9 > 29.6 33.8us 23.8us
|
||||
448 22.2 15.2 > 31.7 44.4us 30.4us
|
||||
512 28.3 19.0 > 32.7 56.6us 38.0us
|
||||
640 42.4 28.0 > 34.0 84.8us 56.0us
|
||||
768 59.4 38.5 > 35.2 118.8us 77.0us
|
||||
896 79.5 51.2 > 35.6 159.0us 102.4us
|
||||
1024 102.6 65.5 > 36.2 205.2us 131.0us
|
||||
1536 224.3 140.6 > 37.3 448.6us 281.2us
|
||||
2048 393.4 244.3 > 37.9 786.8us 488.6us
|
||||
|
||||
------------------------------------------------------------------
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (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.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the
|
||||
License.
|
||||
|
||||
The Original Code is the MPI Arbitrary Precision Integer Arithmetic
|
||||
library.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael J. Fromberger <sting@linguist.dartmouth.edu>
|
||||
Portions created by the Initial Developer are Copyright (C) 1998, 2000
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
$Id: timing.txt,v 1.2 2005-02-02 22:28:22 gerv%gerv.net Exp $
|
||||
|
||||
|
||||
@@ -1,646 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is multacc512 multiple-precision integer arithmetic.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Hewlett-Packard Company.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* coded by: Bill Worley, Hewlett-Packard labs
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
*
|
||||
* This PA-RISC 2.0 function computes the product of two unsigned integers,
|
||||
* and adds the result to a previously computed integer. The multiplicand
|
||||
* is a 512-bit (64-byte, eight doubleword) unsigned integer, stored in
|
||||
* memory in little-double-wordian order. The multiplier is an unsigned
|
||||
* 64-bit integer. The previously computed integer to which the product is
|
||||
* added is located in the result ("res") area, and is assumed to be a
|
||||
* 576-bit (72-byte, nine doubleword) unsigned integer, stored in memory
|
||||
* in little-double-wordian order. This value normally will be the result
|
||||
* of a previously computed nine doubleword result. It is not necessary
|
||||
* to pad the multiplicand with an additional 64-bit zero doubleword.
|
||||
*
|
||||
* Multiplicand, multiplier, and addend ideally should be aligned at
|
||||
* 16-byte boundaries for best performance. The code will function
|
||||
* correctly for alignment at eight-byte boundaries which are not 16-byte
|
||||
* boundaries, but the execution may be slightly slower due to even/odd
|
||||
* bank conflicts on PA-RISC 8000 processors.
|
||||
*
|
||||
* This function is designed to accept the same calling sequence as Bill
|
||||
* Ackerman's "maxpy_little" function. The carry from the ninth doubleword
|
||||
* of the result is written to the tenth word of the result, as is done by
|
||||
* Bill Ackerman's function. The final carry also is returned as an
|
||||
* integer, which may be ignored. The function prototype may be either
|
||||
* of the following:
|
||||
*
|
||||
* void multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
* or
|
||||
* int multacc512( int l, chunk* m, const chunk* a, chunk* res );
|
||||
*
|
||||
* where: "l" originally denoted vector lengths. This parameter is
|
||||
* ignored. This function always assumes a multiplicand length of
|
||||
* 512 bits (eight doublewords), and addend and result lengths of
|
||||
* 576 bits (nine doublewords).
|
||||
*
|
||||
* "m" is a pointer to the doubleword multiplier, ideally aligned
|
||||
* on a 16-byte boundary.
|
||||
*
|
||||
* "a" is a pointer to the eight-doubleword multiplicand, stored
|
||||
* in little-double-wordian order, and ideally aligned on a 16-byte
|
||||
* boundary.
|
||||
*
|
||||
* "res" is a pointer to the nine doubleword addend, and to the
|
||||
* nine-doubleword product computed by this function. The result
|
||||
* also is stored in little-double-wordian order, and ideally is
|
||||
* aligned on a 16-byte boundary. It is expected that the alignment
|
||||
* of the "res" area may alternate between even/odd doubleword
|
||||
* boundaries for successive calls for 512-bit x 512-bit
|
||||
* multiplications.
|
||||
*
|
||||
* The code for this function has been scheduled to use the parallelism
|
||||
* of the PA-RISC 8000 series microprocessors as well as the author was
|
||||
* able. Comments and/or suggestions for improvement are welcomed.
|
||||
*
|
||||
* The code is "64-bit safe". This means it may be called in either
|
||||
* the 32ILP context or the 64LP context. All 64-bits of registers are
|
||||
* saved and restored.
|
||||
*
|
||||
* This code is self-contained. It requires no other header files in order
|
||||
* to compile and to be linkable on a PA-RISC 2.0 machine. Symbolic
|
||||
* definitions for registers and stack offsets are included within this
|
||||
* one source file.
|
||||
*
|
||||
* This is a leaf routine. As such, minimal use is made of the stack area.
|
||||
* Of the 192 bytes allocated, 64 bytes are used for saving/restoring eight
|
||||
* general registers, and 128 bytes are used to move intermediate products
|
||||
* from the floating-point registers to the general registers. Stack
|
||||
* protocols assure proper alignment of these areas.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* ====================================================================*/
|
||||
/* symbolic definitions for PA-RISC registers */
|
||||
/* in the MIPS style, avoids lots of case shifts */
|
||||
/* assigments (except t4) preserve register number parity */
|
||||
/* ====================================================================*/
|
||||
|
||||
#define zero %r0 /* permanent zero */
|
||||
#define t5 %r1 /* temp register, altered by addil */
|
||||
|
||||
#define rp %r2 /* return pointer */
|
||||
|
||||
#define s1 %r3 /* callee saves register*/
|
||||
#define s0 %r4 /* callee saves register*/
|
||||
#define s3 %r5 /* callee saves register*/
|
||||
#define s2 %r6 /* callee saves register*/
|
||||
#define s5 %r7 /* callee saves register*/
|
||||
#define s4 %r8 /* callee saves register*/
|
||||
#define s7 %r9 /* callee saves register*/
|
||||
#define s6 %r10 /* callee saves register*/
|
||||
|
||||
#define t1 %r19 /* caller saves register*/
|
||||
#define t0 %r20 /* caller saves register*/
|
||||
#define t3 %r21 /* caller saves register*/
|
||||
#define t2 %r22 /* caller saves register*/
|
||||
|
||||
#define a3 %r23 /* fourth argument register, high word */
|
||||
#define a2 %r24 /* third argument register, low word*/
|
||||
#define a1 %r25 /* second argument register, high word*/
|
||||
#define a0 %r26 /* first argument register, low word*/
|
||||
|
||||
#define v0 %r28 /* high order return value*/
|
||||
#define v1 %r29 /* low order return value*/
|
||||
|
||||
#define sp %r30 /* stack pointer*/
|
||||
#define t4 %r31 /* temporary register */
|
||||
|
||||
#define fa0 %fr4 /* first argument register*/
|
||||
#define fa1 %fr5 /* second argument register*/
|
||||
#define fa2 %fr6 /* third argument register*/
|
||||
#define fa3 %fr7 /* fourth argument register*/
|
||||
|
||||
#define fa0r %fr4R /* first argument register*/
|
||||
#define fa1r %fr5R /* second argument register*/
|
||||
#define fa2r %fr6R /* third argument register*/
|
||||
#define fa3r %fr7R /* fourth argument register*/
|
||||
|
||||
#define ft0 %fr8 /* caller saves register*/
|
||||
#define ft1 %fr9 /* caller saves register*/
|
||||
#define ft2 %fr10 /* caller saves register*/
|
||||
#define ft3 %fr11 /* caller saves register*/
|
||||
|
||||
#define ft0r %fr8R /* caller saves register*/
|
||||
#define ft1r %fr9R /* caller saves register*/
|
||||
#define ft2r %fr10R /* caller saves register*/
|
||||
#define ft3r %fr11R /* caller saves register*/
|
||||
|
||||
#define ft4 %fr22 /* caller saves register*/
|
||||
#define ft5 %fr23 /* caller saves register*/
|
||||
#define ft6 %fr24 /* caller saves register*/
|
||||
#define ft7 %fr25 /* caller saves register*/
|
||||
#define ft8 %fr26 /* caller saves register*/
|
||||
#define ft9 %fr27 /* caller saves register*/
|
||||
#define ft10 %fr28 /* caller saves register*/
|
||||
#define ft11 %fr29 /* caller saves register*/
|
||||
#define ft12 %fr30 /* caller saves register*/
|
||||
#define ft13 %fr31 /* caller saves register*/
|
||||
|
||||
#define ft4r %fr22R /* caller saves register*/
|
||||
#define ft5r %fr23R /* caller saves register*/
|
||||
#define ft6r %fr24R /* caller saves register*/
|
||||
#define ft7r %fr25R /* caller saves register*/
|
||||
#define ft8r %fr26R /* caller saves register*/
|
||||
#define ft9r %fr27R /* caller saves register*/
|
||||
#define ft10r %fr28R /* caller saves register*/
|
||||
#define ft11r %fr29R /* caller saves register*/
|
||||
#define ft12r %fr30R /* caller saves register*/
|
||||
#define ft13r %fr31R /* caller saves register*/
|
||||
|
||||
|
||||
|
||||
/* ================================================================== */
|
||||
/* functional definitions for PA-RISC registers */
|
||||
/* ================================================================== */
|
||||
|
||||
/* general registers */
|
||||
|
||||
#define T1 a0 /* temp, (length parameter ignored) */
|
||||
|
||||
#define pM a1 /* -> 64-bit multiplier */
|
||||
#define T2 a1 /* temp, (after fetching multiplier) */
|
||||
|
||||
#define pA a2 /* -> multiplicand vector (8 64-bit words) */
|
||||
#define T3 a2 /* temp, (after fetching multiplicand) */
|
||||
|
||||
#define pR a3 /* -> addend vector (8 64-bit doublewords,
|
||||
result vector (9 64-bit words) */
|
||||
|
||||
#define S0 s0 /* callee saves summand registers */
|
||||
#define S1 s1
|
||||
#define S2 s2
|
||||
#define S3 s3
|
||||
#define S4 s4
|
||||
#define S5 s5
|
||||
#define S6 s6
|
||||
#define S7 s7
|
||||
|
||||
#define S8 v0 /* caller saves summand registers */
|
||||
#define S9 v1
|
||||
#define S10 t0
|
||||
#define S11 t1
|
||||
#define S12 t2
|
||||
#define S13 t3
|
||||
#define S14 t4
|
||||
#define S15 t5
|
||||
|
||||
|
||||
|
||||
/* floating-point registers */
|
||||
|
||||
#define M fa0 /* multiplier double word */
|
||||
#define MR fa0r /* low order half of multiplier double word */
|
||||
#define ML fa0 /* high order half of multiplier double word */
|
||||
|
||||
#define A0 fa2 /* multiplicand double word 0 */
|
||||
#define A0R fa2r /* low order half of multiplicand double word */
|
||||
#define A0L fa2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A1 fa3 /* multiplicand double word 1 */
|
||||
#define A1R fa3r /* low order half of multiplicand double word */
|
||||
#define A1L fa3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A2 ft0 /* multiplicand double word 2 */
|
||||
#define A2R ft0r /* low order half of multiplicand double word */
|
||||
#define A2L ft0 /* high order half of multiplicand double word */
|
||||
|
||||
#define A3 ft1 /* multiplicand double word 3 */
|
||||
#define A3R ft1r /* low order half of multiplicand double word */
|
||||
#define A3L ft1 /* high order half of multiplicand double word */
|
||||
|
||||
#define A4 ft2 /* multiplicand double word 4 */
|
||||
#define A4R ft2r /* low order half of multiplicand double word */
|
||||
#define A4L ft2 /* high order half of multiplicand double word */
|
||||
|
||||
#define A5 ft3 /* multiplicand double word 5 */
|
||||
#define A5R ft3r /* low order half of multiplicand double word */
|
||||
#define A5L ft3 /* high order half of multiplicand double word */
|
||||
|
||||
#define A6 ft4 /* multiplicand double word 6 */
|
||||
#define A6R ft4r /* low order half of multiplicand double word */
|
||||
#define A6L ft4 /* high order half of multiplicand double word */
|
||||
|
||||
#define A7 ft5 /* multiplicand double word 7 */
|
||||
#define A7R ft5r /* low order half of multiplicand double word */
|
||||
#define A7L ft5 /* high order half of multiplicand double word */
|
||||
|
||||
#define P0 ft6 /* product word 0 */
|
||||
#define P1 ft7 /* product word 0 */
|
||||
#define P2 ft8 /* product word 0 */
|
||||
#define P3 ft9 /* product word 0 */
|
||||
#define P4 ft10 /* product word 0 */
|
||||
#define P5 ft11 /* product word 0 */
|
||||
#define P6 ft12 /* product word 0 */
|
||||
#define P7 ft13 /* product word 0 */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* symbolic definitions for HP-UX stack offsets */
|
||||
/* symbolic definitions for memory NOPs */
|
||||
/* ====================================================================== */
|
||||
|
||||
#define ST_SZ 192 /* stack area total size */
|
||||
|
||||
#define SV0 -192(sp) /* general register save area */
|
||||
#define SV1 -184(sp)
|
||||
#define SV2 -176(sp)
|
||||
#define SV3 -168(sp)
|
||||
#define SV4 -160(sp)
|
||||
#define SV5 -152(sp)
|
||||
#define SV6 -144(sp)
|
||||
#define SV7 -136(sp)
|
||||
|
||||
#define XF0 -128(sp) /* data transfer area */
|
||||
#define XF1 -120(sp) /* for floating-pt to integer regs */
|
||||
#define XF2 -112(sp)
|
||||
#define XF3 -104(sp)
|
||||
#define XF4 -96(sp)
|
||||
#define XF5 -88(sp)
|
||||
#define XF6 -80(sp)
|
||||
#define XF7 -72(sp)
|
||||
#define XF8 -64(sp)
|
||||
#define XF9 -56(sp)
|
||||
#define XF10 -48(sp)
|
||||
#define XF11 -40(sp)
|
||||
#define XF12 -32(sp)
|
||||
#define XF13 -24(sp)
|
||||
#define XF14 -16(sp)
|
||||
#define XF15 -8(sp)
|
||||
|
||||
#define mnop proberi (sp),3,zero /* memory NOP */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
/* assembler formalities */
|
||||
/* ====================================================================== */
|
||||
|
||||
#ifdef __LP64__
|
||||
.level 2.0W
|
||||
#else
|
||||
.level 2.0
|
||||
#endif
|
||||
.space $TEXT$
|
||||
.subspa $CODE$
|
||||
.align 16
|
||||
|
||||
/* ====================================================================== */
|
||||
/* here to compute 64-bit x 512-bit product + 512-bit addend */
|
||||
/* ====================================================================== */
|
||||
|
||||
multacc512
|
||||
.PROC
|
||||
.CALLINFO
|
||||
.ENTER
|
||||
fldd 0(pM),M ; multiplier double word
|
||||
ldo ST_SZ(sp),sp ; push stack
|
||||
|
||||
fldd 0(pA),A0 ; multiplicand double word 0
|
||||
std S1,SV1 ; save s1
|
||||
|
||||
fldd 16(pA),A2 ; multiplicand double word 2
|
||||
std S3,SV3 ; save s3
|
||||
|
||||
fldd 32(pA),A4 ; multiplicand double word 4
|
||||
std S5,SV5 ; save s5
|
||||
|
||||
fldd 48(pA),A6 ; multiplicand double word 6
|
||||
std S7,SV7 ; save s7
|
||||
|
||||
|
||||
std S0,SV0 ; save s0
|
||||
fldd 8(pA),A1 ; multiplicand double word 1
|
||||
xmpyu MR,A0L,P0 ; A0 cross 32-bit word products
|
||||
xmpyu ML,A0R,P2
|
||||
|
||||
std S2,SV2 ; save s2
|
||||
fldd 24(pA),A3 ; multiplicand double word 3
|
||||
xmpyu MR,A2L,P4 ; A2 cross 32-bit word products
|
||||
xmpyu ML,A2R,P6
|
||||
|
||||
std S4,SV4 ; save s4
|
||||
fldd 40(pA),A5 ; multiplicand double word 5
|
||||
|
||||
std S6,SV6 ; save s6
|
||||
fldd 56(pA),A7 ; multiplicand double word 7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0L
|
||||
xmpyu MR,A0R,P0 ; A0 right 32-bit word product
|
||||
xmpyu MR,A1L,P1 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P2,XF2 ; ML * A0R
|
||||
xmpyu ML,A0L,P2 ; A0 left 32-bit word product
|
||||
xmpyu ML,A1R,P3 ; A1 cross 32-bit word product
|
||||
|
||||
fstd P4,XF4 ; MR * A2L
|
||||
xmpyu MR,A2R,P4 ; A2 right 32-bit word product
|
||||
xmpyu MR,A3L,P5 ; A3 cross 32-bit word product
|
||||
|
||||
fstd P6,XF6 ; ML * A2R
|
||||
xmpyu ML,A2L,P6 ; A2 parallel 32-bit word product
|
||||
xmpyu ML,A3R,P7 ; A3 cross 32-bit word product
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A0L
|
||||
fstd P1,XF1 ; MR * A1L
|
||||
|
||||
ldd XF2,S2 ; ML * A0R
|
||||
fstd P3,XF3 ; ML * A1R
|
||||
|
||||
ldd XF4,S4 ; MR * A2L
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A1R,P1 ; A1 parallel 32-bit word products
|
||||
xmpyu ML,A1L,P3
|
||||
|
||||
ldd XF6,S6 ; ML * A2R
|
||||
fstd P7,XF7 ; ML * A3R
|
||||
xmpyu MR,A3R,P5 ; A3 parallel 32-bit word products
|
||||
xmpyu ML,A3L,P7
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A0R
|
||||
ldd XF1,S1 ; MR * A1L
|
||||
nop
|
||||
add S0,S2,T1 ; A0 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A0L
|
||||
ldd XF3,S3 ; ML * A1R
|
||||
add,dc zero,zero,S0 ; A0 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A0 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A2R
|
||||
ldd XF5,S5 ; MR * A3L
|
||||
shrpd S0,T1,32,S0 ; A0 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A2 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A2L
|
||||
ldd XF7,S7 ; ML * A3R
|
||||
add,dc zero,zero,S4 ; A2 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A2 cross product sum << 32
|
||||
|
||||
|
||||
ldd XF0,S8 ; MR * A0R
|
||||
fstd P1,XF1 ; MR * A1R
|
||||
xmpyu MR,A4L,P0 ; A4 cross 32-bit word product
|
||||
xmpyu MR,A5L,P1 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF2,S10 ; ML * A0L
|
||||
fstd P3,XF3 ; ML * A1L
|
||||
xmpyu ML,A4R,P2 ; A4 cross 32-bit word product
|
||||
xmpyu ML,A5R,P3 ; A5 cross 32-bit word product
|
||||
|
||||
ldd XF4,S12 ; MR * A2R
|
||||
fstd P5,XF5 ; MR * A3L
|
||||
xmpyu MR,A6L,P4 ; A6 cross 32-bit word product
|
||||
xmpyu MR,A7L,P5 ; A7 cross 32-bit word product
|
||||
|
||||
ldd XF6,S14 ; ML * A2L
|
||||
fstd P7,XF7 ; ML * A3L
|
||||
xmpyu ML,A6R,P6 ; A6 cross 32-bit word product
|
||||
xmpyu ML,A7R,P7 ; A7 cross 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4L
|
||||
ldd XF1,S9 ; MR * A1R
|
||||
shrpd S4,T3,32,S4 ; A2 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A1 cross product sum
|
||||
|
||||
fstd P2,XF2 ; ML * A4R
|
||||
ldd XF3,S11 ; ML * A1L
|
||||
add,dc zero,zero,S1 ; A1 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A1 cross product sum << 32
|
||||
|
||||
fstd P4,XF4 ; MR * A6L
|
||||
ldd XF5,S13 ; MR * A3R
|
||||
shrpd S1,T1,32,S1 ; A1 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A3 cross product sum
|
||||
|
||||
fstd P6,XF6 ; ML * A6R
|
||||
ldd XF7,S15 ; ML * A3L
|
||||
add,dc zero,zero,S5 ; A3 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A3 cross product sum << 32
|
||||
|
||||
|
||||
shrpd S5,T3,32,S5 ; A3 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A0 right doubleword, P0 doubleword
|
||||
|
||||
add,dc S0,S10,S10 ; M * A0 left doubleword
|
||||
add S3,S9,S9 ; M * A1 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A1 left doubleword
|
||||
add S6,S12,S12 ; M * A2 right doubleword
|
||||
|
||||
|
||||
ldd 24(pR),S3 ; Addend word 3
|
||||
fstd P1,XF1 ; MR * A5L
|
||||
add,dc S4,S14,S14 ; M * A2 left doubleword
|
||||
xmpyu MR,A5R,P1 ; A5 right 32-bit word product
|
||||
|
||||
ldd 8(pR),S1 ; Addend word 1
|
||||
fstd P3,XF3 ; ML * A5R
|
||||
add S7,S13,S13 ; M * A3 right doubleword
|
||||
xmpyu ML,A5L,P3 ; A5 left 32-bit word product
|
||||
|
||||
ldd 0(pR),S7 ; Addend word 0
|
||||
fstd P5,XF5 ; MR * A7L
|
||||
add,dc S5,S15,S15 ; M * A3 left doubleword
|
||||
xmpyu MR,A7R,P5 ; A7 right 32-bit word product
|
||||
|
||||
ldd 16(pR),S5 ; Addend word 2
|
||||
fstd P7,XF7 ; ML * A7R
|
||||
add S10,S9,S9 ; P1 doubleword
|
||||
xmpyu ML,A7L,P7 ; A7 left 32-bit word products
|
||||
|
||||
|
||||
ldd XF0,S0 ; MR * A4L
|
||||
fstd P1,XF9 ; MR * A5R
|
||||
add,dc S11,S12,S12 ; P2 doubleword
|
||||
xmpyu MR,A4R,P0 ; A4 right 32-bit word product
|
||||
|
||||
ldd XF2,S2 ; ML * A4R
|
||||
fstd P3,XF11 ; ML * A5L
|
||||
add,dc S14,S13,S13 ; P3 doubleword
|
||||
xmpyu ML,A4L,P2 ; A4 left 32-bit word product
|
||||
|
||||
ldd XF6,S6 ; ML * A6R
|
||||
fstd P5,XF13 ; MR * A7R
|
||||
add,dc zero,S15,T2 ; P4 partial doubleword
|
||||
xmpyu MR,A6R,P4 ; A6 right 32-bit word product
|
||||
|
||||
ldd XF4,S4 ; MR * A6L
|
||||
fstd P7,XF15 ; ML * A7L
|
||||
add S7,S8,S8 ; R0 + P0, new R0 doubleword
|
||||
xmpyu ML,A6L,P6 ; A6 left 32-bit word product
|
||||
|
||||
|
||||
fstd P0,XF0 ; MR * A4R
|
||||
ldd XF7,S7 ; ML * A7R
|
||||
add,dc S1,S9,S9 ; c + R1 + P1, new R1 doubleword
|
||||
|
||||
fstd P2,XF2 ; ML * A4L
|
||||
ldd XF1,S1 ; MR * A5L
|
||||
add,dc S5,S12,S12 ; c + R2 + P2, new R2 doubleword
|
||||
|
||||
fstd P4,XF4 ; MR * A6R
|
||||
ldd XF5,S5 ; MR * A7L
|
||||
add,dc S3,S13,S13 ; c + R3 + P3, new R3 doubleword
|
||||
|
||||
fstd P6,XF6 ; ML * A6L
|
||||
ldd XF3,S3 ; ML * A5R
|
||||
add,dc zero,T2,T2 ; c + partial P4
|
||||
add S0,S2,T1 ; A4 cross product sum
|
||||
|
||||
|
||||
std S8,0(pR) ; save R0
|
||||
add,dc zero,zero,S0 ; A4 cross product sum carry
|
||||
depd,z T1,31,32,S2 ; A4 cross product sum << 32
|
||||
|
||||
std S9,8(pR) ; save R1
|
||||
shrpd S0,T1,32,S0 ; A4 carry | cross product sum >> 32
|
||||
add S4,S6,T3 ; A6 cross product sum
|
||||
|
||||
std S12,16(pR) ; save R2
|
||||
add,dc zero,zero,S4 ; A6 cross product sum carry
|
||||
depd,z T3,31,32,S6 ; A6 cross product sum << 32
|
||||
|
||||
|
||||
std S13,24(pR) ; save R3
|
||||
shrpd S4,T3,32,S4 ; A6 carry | cross product sum >> 32
|
||||
add S1,S3,T1 ; A5 cross product sum
|
||||
|
||||
ldd XF0,S8 ; MR * A4R
|
||||
add,dc zero,zero,S1 ; A5 cross product sum carry
|
||||
depd,z T1,31,32,S3 ; A5 cross product sum << 32
|
||||
|
||||
ldd XF2,S10 ; ML * A4L
|
||||
ldd XF9,S9 ; MR * A5R
|
||||
shrpd S1,T1,32,S1 ; A5 carry | cross product sum >> 32
|
||||
add S5,S7,T3 ; A7 cross product sum
|
||||
|
||||
ldd XF4,S12 ; MR * A6R
|
||||
ldd XF11,S11 ; ML * A5L
|
||||
add,dc zero,zero,S5 ; A7 cross product sum carry
|
||||
depd,z T3,31,32,S7 ; A7 cross product sum << 32
|
||||
|
||||
ldd XF6,S14 ; ML * A6L
|
||||
ldd XF13,S13 ; MR * A7R
|
||||
shrpd S5,T3,32,S5 ; A7 carry | cross product sum >> 32
|
||||
add S2,S8,S8 ; M * A4 right doubleword
|
||||
|
||||
|
||||
ldd XF15,S15 ; ML * A7L
|
||||
add,dc S0,S10,S10 ; M * A4 left doubleword
|
||||
add S3,S9,S9 ; M * A5 right doubleword
|
||||
|
||||
add,dc S1,S11,S11 ; M * A5 left doubleword
|
||||
add S6,S12,S12 ; M * A6 right doubleword
|
||||
|
||||
ldd 32(pR),S0 ; Addend word 4
|
||||
ldd 40(pR),S1 ; Addend word 5
|
||||
add,dc S4,S14,S14 ; M * A6 left doubleword
|
||||
add S7,S13,S13 ; M * A7 right doubleword
|
||||
|
||||
ldd 48(pR),S2 ; Addend word 6
|
||||
ldd 56(pR),S3 ; Addend word 7
|
||||
add,dc S5,S15,S15 ; M * A7 left doubleword
|
||||
add S8,T2,S8 ; P4 doubleword
|
||||
|
||||
ldd 64(pR),S4 ; Addend word 8
|
||||
ldd SV5,s5 ; restore s5
|
||||
add,dc S10,S9,S9 ; P5 doubleword
|
||||
add,dc S11,S12,S12 ; P6 doubleword
|
||||
|
||||
|
||||
ldd SV6,s6 ; restore s6
|
||||
ldd SV7,s7 ; restore s7
|
||||
add,dc S14,S13,S13 ; P7 doubleword
|
||||
add,dc zero,S15,S15 ; P8 doubleword
|
||||
|
||||
add S0,S8,S8 ; new R4 doubleword
|
||||
|
||||
ldd SV0,s0 ; restore s0
|
||||
std S8,32(pR) ; save R4
|
||||
add,dc S1,S9,S9 ; new R5 doubleword
|
||||
|
||||
ldd SV1,s1 ; restore s1
|
||||
std S9,40(pR) ; save R5
|
||||
add,dc S2,S12,S12 ; new R6 doubleword
|
||||
|
||||
ldd SV2,s2 ; restore s2
|
||||
std S12,48(pR) ; save R6
|
||||
add,dc S3,S13,S13 ; new R7 doubleword
|
||||
|
||||
ldd SV3,s3 ; restore s3
|
||||
std S13,56(pR) ; save R7
|
||||
add,dc S4,S15,S15 ; new R8 doubleword
|
||||
|
||||
ldd SV4,s4 ; restore s4
|
||||
std S15,64(pR) ; save result[8]
|
||||
add,dc zero,zero,v0 ; return carry from R8
|
||||
|
||||
CMPIB,*= 0,v0,$L0 ; if no overflow, exit
|
||||
LDO 8(pR),pR
|
||||
|
||||
$FINAL1 ; Final carry propagation
|
||||
LDD 64(pR),v0
|
||||
LDO 8(pR),pR
|
||||
ADDI 1,v0,v0
|
||||
CMPIB,*= 0,v0,$FINAL1 ; Keep looping if there is a carry.
|
||||
STD v0,56(pR)
|
||||
$L0
|
||||
bv zero(rp) ; -> caller
|
||||
ldo -ST_SZ(sp),sp ; pop stack
|
||||
|
||||
/* ====================================================================== */
|
||||
/* end of module */
|
||||
/* ====================================================================== */
|
||||
|
||||
.LEAVE
|
||||
|
||||
.PROCEND
|
||||
.SPACE $TEXT$
|
||||
.SUBSPA $CODE$
|
||||
.EXPORT multacc512,ENTRY
|
||||
|
||||
.end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user