Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
258dc9fead This commit was manufactured by cvs2svn to create branch 'src'.
git-svn-id: svn://10.0.0.236/branches/src@33658 18797224-902f-48f8-a5cc-f745e15eee43
1999-06-03 23:10:01 +00:00
321 changed files with 18627 additions and 120041 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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, &params->prime) );
SECITEM_TO_MPINT(key->prime, &p);
/* Set private key's g */
CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->base, &params->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;
}

View File

@@ -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,
&params->prime) );
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
&params->subPrime) );
CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, &params->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

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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:
;+ *;
;+};

View File

@@ -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

View File

@@ -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__;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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(&microTickCount);
return CopyLowBits(buf, maxbytes, &microTickCount, 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

View File

@@ -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

View File

@@ -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:
*;
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 *****

View File

@@ -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 $

View File

@@ -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."

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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 $

View File

@@ -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