diff options
author | cvs2hg <devnull@localhost> | 2003-12-23 00:52:07 +0000 |
---|---|---|
committer | cvs2hg <devnull@localhost> | 2003-12-23 00:52:07 +0000 |
commit | 7ae644ebb6243b9c58f364084eb53a017e8a5289 (patch) | |
tree | 49c5db698b2f992b440b2ac8bff22fbb1274a91d | |
parent | 26b3b7b10e75bc46874b5c64058bd86929855d7b (diff) | |
download | nss-hg-7ae644ebb6243b9c58f364084eb53a017e8a5289.tar.gz |
fixup commit for branch 'MOZILLA_1_4_BRANCH'
46 files changed, 12559 insertions, 0 deletions
diff --git a/security/coreconf/AIX5.2.mk b/security/coreconf/AIX5.2.mk new file mode 100644 index 000000000..319569c52 --- /dev/null +++ b/security/coreconf/AIX5.2.mk @@ -0,0 +1,54 @@ +# +# 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# Config stuff for AIX5.2 +# + +include $(CORE_DEPTH)/coreconf/AIX.mk + + +ifeq ($(USE_64), 1) +# Next line replaced by generic name handling in arch.mk +# COMPILER_TAG = _64 + OS_CFLAGS += -DAIX_64BIT + OBJECT_MODE=64 + export OBJECT_MODE +endif +DSO_LDOPTS = -brtl -bM:SRE -bnoentry +MKSHLIB = $(LD) $(DSO_LDOPTS) -blibpath:/usr/lib:/lib -lc -lm + +OS_LIBS += -blibpath:/usr/lib:/lib -lc -lm +ifdef MAPFILE +DSO_LDOPTS += -bexport:$(MAPFILE) +else +DSO_LDOPTS += -bexpall +endif diff --git a/security/coreconf/Linux2.6.mk b/security/coreconf/Linux2.6.mk new file mode 100644 index 000000000..602b3abe1 --- /dev/null +++ b/security/coreconf/Linux2.6.mk @@ -0,0 +1,49 @@ +# +# 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# Config stuff for Linux 2.6 (ELF) +# + +include $(CORE_DEPTH)/coreconf/Linux.mk + +OS_REL_CFLAGS += -DLINUX2_1 +MKSHLIB = $(CC) -shared -Wl,-soname -Wl,$(@:$(OBJDIR)/%.so=%.so) +ifdef BUILD_OPT + OPTIMIZER = -O2 +endif + +ifdef MAPFILE + MKSHLIB += -Wl,--version-script,$(MAPFILE) +endif +PROCESS_MAP_FILE = grep -v ';-' $(LIBRARY_NAME).def | \ + sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@ + diff --git a/security/nss/lib/freebl/ecl/Makefile b/security/nss/lib/freebl/ecl/Makefile new file mode 100644 index 000000000..5ee99a730 --- /dev/null +++ b/security/nss/lib/freebl/ecl/Makefile @@ -0,0 +1,224 @@ +## +## Makefile for elliptic curve library +## +## 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. +## +## Portions created by Michael J. Fromberger are +## Copyright (C) 1998, 2000 Michael J. Fromberger. 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 the GNU General Public License Version 2 or later (the +## "GPL"), in which case the provisions of the GPL are applicable +## instead of those above. If you wish to allow use of your +## version of this file only under the terms of the GPL and not to +## allow others to use your version of this file under the MPL, +## indicate your decision by deleting the provisions above and +## replace them with the notice and other provisions required by +## the GPL. If you do not delete the provisions above, a recipient +## may use your version of this file under either the MPL or the +## GPL. + +## 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 +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_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 diff --git a/security/nss/lib/freebl/ecl/README b/security/nss/lib/freebl/ecl/README new file mode 100644 index 000000000..d12eb3610 --- /dev/null +++ b/security/nss/lib/freebl/ecl/README @@ -0,0 +1,329 @@ + +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. + + +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 diff --git a/security/nss/lib/freebl/ecl/README.FP b/security/nss/lib/freebl/ecl/README.FP new file mode 100644 index 000000000..e92a5affe --- /dev/null +++ b/security/nss/lib/freebl/ecl/README.FP @@ -0,0 +1,316 @@ + +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. + + +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. diff --git a/security/nss/lib/freebl/ecl/ec2.h b/security/nss/lib/freebl/ecl/ec2.h new file mode 100644 index 000000000..2c66b55f5 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2.h @@ -0,0 +1,122 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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); + +/* 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_ */ diff --git a/security/nss/lib/freebl/ecl/ec2_163.c b/security/nss/lib/freebl/ecl/ec2_163.c new file mode 100644 index 000000000..d6872500d --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_163.c @@ -0,0 +1,258 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ec2_193.c b/security/nss/lib/freebl/ecl/ec2_193.c new file mode 100644 index 000000000..5035a99bd --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_193.c @@ -0,0 +1,275 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ec2_233.c b/security/nss/lib/freebl/ecl/ec2_233.c new file mode 100644 index 000000000..719854229 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_233.c @@ -0,0 +1,298 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ec2_aff.c b/security/nss/lib/freebl/ecl/ec2_aff.c new file mode 100644 index 000000000..5c7972c0c --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_aff.c @@ -0,0 +1,270 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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 diff --git a/security/nss/lib/freebl/ecl/ec2_mont.c b/security/nss/lib/freebl/ecl/ec2_mont.c new file mode 100644 index 000000000..6658d3295 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_mont.c @@ -0,0 +1,276 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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(rx, &x2)); /* x2 = rx */ + MP_CHECKOK(mp_copy(ry, &z2)); /* z2 = ry */ + + 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 = + * x2^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; +} diff --git a/security/nss/lib/freebl/ecl/ec2_proj.c b/security/nss/lib/freebl/ecl/ec2_proj.c new file mode 100644 index 000000000..8df72433c --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_proj.c @@ -0,0 +1,368 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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 diff --git a/security/nss/lib/freebl/ecl/ec_naf.c b/security/nss/lib/freebl/ecl/ec_naf.c new file mode 100644 index 000000000..a6b04add8 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec_naf.c @@ -0,0 +1,101 @@ +/* + * 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>, 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. + * + */ + +#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; + +} diff --git a/security/nss/lib/freebl/ecl/ecl-curve.h b/security/nss/lib/freebl/ecl/ecl-curve.h new file mode 100644 index 000000000..5c03f3a84 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-curve.h @@ -0,0 +1,646 @@ +/* + * 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): + * 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. + * + */ + +#include "ecl-exp.h" +#include <stdlib.h> + +#ifndef __ecl_curve_h_ +#define __ecl_curve_h_ + +/* 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 diff --git a/security/nss/lib/freebl/ecl/ecl-exp.h b/security/nss/lib/freebl/ecl/ecl-exp.h new file mode 100644 index 000000000..1a3421c81 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-exp.h @@ -0,0 +1,194 @@ +/* + * 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): + * 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. + * + */ + +#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_ */ diff --git a/security/nss/lib/freebl/ecl/ecl-priv.h b/security/nss/lib/freebl/ecl/ecl-priv.h new file mode 100644 index 000000000..908ed8ebc --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-priv.h @@ -0,0 +1,216 @@ +/* + * 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. + * + */ + +#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 */ +#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT) +#define ECL_SIXTY_FOUR_BIT +#define ECL_BITS 64 +#define ECL_MAX_FIELD_SIZE_DIGITS 10 +#else +#define ECL_THIRTY_TWO_BIT +#define ECL_BITS 32 +#define ECL_MAX_FIELD_SIZE_DIGITS 20 +#endif + +/* 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)) + +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); + /* 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); +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_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_ */ diff --git a/security/nss/lib/freebl/ecl/ecl.c b/security/nss/lib/freebl/ecl/ecl.c new file mode 100644 index 000000000..9d7af0624 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl.c @@ -0,0 +1,406 @@ +/* + * 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): + * 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. + * + */ + +#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->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; + 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)); + group->base_point_mul = NULL; + group->points_mul = NULL; + group->extra1 = NULL; + group->extra2 = NULL; + group->extra_free = NULL; + + 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; + + 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; + + CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; +} + +/* 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; + + CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; +} + +/* Helper macros for ecgroup_fromNameAndHex. */ +#define CHECK_GROUP \ + if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } +#define CONS_GF2M \ + group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor); \ + CHECK_GROUP + +/* 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) { + if ((name == ECCurve_SECG_PRIME_160K1) + || (name == ECCurve_SECG_PRIME_160R2)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + } else if ((name == ECCurve_SECG_PRIME_160R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_secp160r1_fp(group)); +#else + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); +#endif + } else if ((name == ECCurve_SECG_PRIME_192K1)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp192(group, name)); + } else if ((name == ECCurve_SECG_PRIME_192R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_nistp192_fp(group)); +#else + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp192(group, name)); +#endif + } else if ((name == ECCurve_SECG_PRIME_224K1)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp224(group, name)); + } else if ((name == ECCurve_SECG_PRIME_224R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_nistp224_fp(group)); +#else + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp224(group, name)); +#endif + } else { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP} + /* XXX secp521r1 fails ecp_test with &ec_GFp_pts_mul_jac */ + if (name == ECCurve_SECG_PRIME_521R1) { + group->points_mul = &ec_pts_mul_simul_w2; + } + } else if (params->field == ECField_GF2m) { + switch (bits) { + case 163: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m163(group, name)); + break; + case 193: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m193(group, name)); + break; + case 233: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m233(group, name)); + break; + default: + group = + ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, + &geny, &order, params->cofactor); + CHECK_GROUP break; + } + } + + /* set name, if any */ + if (params->text != NULL) { + group->text = (char *) malloc(sizeof(char) * strlen(params->text)); + if (group->text == NULL) { + res = MP_MEM; + } + strcpy(group->text, params->text); + } + + 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; +} + +#undef CHECK_GROUP +#undef CONS_GFP +#undef CONS_GF2M + +/* 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; +} + +/* 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; + if (group->text != NULL) + free(group->text); + if (group->extra_free != NULL) + group->extra_free(group); + free(group); +} diff --git a/security/nss/lib/freebl/ecl/ecl.h b/security/nss/lib/freebl/ecl/ecl.h new file mode 100644 index 000000000..7db9deb0a --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl.h @@ -0,0 +1,82 @@ +/* + * 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): + * 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. + * + */ + +/* 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); + +#endif /* __ecl_h_ */ diff --git a/security/nss/lib/freebl/ecl/ecl_curve.c b/security/nss/lib/freebl/ecl/ecl_curve.c new file mode 100644 index 000000000..d8368092e --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_curve.c @@ -0,0 +1,120 @@ +/* + * 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): + * 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. + * + */ + +#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 *) malloc(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)) { + 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); +} diff --git a/security/nss/lib/freebl/ecl/ecl_gf.c b/security/nss/lib/freebl/ecl/ecl_gf.c new file mode 100644 index 000000000..000f97b86 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_gf.c @@ -0,0 +1,337 @@ +/* + * 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. + * + */ + +#include "mpi.h" +#include "mp_gf2m.h" +#include "ecl-priv.h" +#include <stdlib.h> + +/* Allocate memory for a new GFMethod object. */ +GFMethod * +GFMethod_new() +{ + mp_err res = MP_OKAY; + GFMethod *meth; + meth = (GFMethod *) malloc(sizeof(GFMethod)); + if (meth == NULL) + return NULL; + meth->constructed = MP_YES; + MP_CHECKOK(mp_init(&meth->irr)); + meth->extra_free = NULL; + + CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; +} + +/* Construct a generic GFMethod for arithmetic over prime fields with + * irreducible irr. */ +GFMethod * +GFMethod_consGFp(const mp_int *irr) +{ + mp_err res = MP_OKAY; + GFMethod *meth = NULL; + + meth = GFMethod_new(); + if (meth == NULL) + return NULL; + + MP_CHECKOK(mp_copy(irr, &meth->irr)); + meth->irr_arr[0] = mpl_significant_bits(irr); + meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] = + meth->irr_arr[4] = 0; + meth->field_add = &ec_GFp_add; + meth->field_neg = &ec_GFp_neg; + meth->field_sub = &ec_GFp_sub; + meth->field_mod = &ec_GFp_mod; + meth->field_mul = &ec_GFp_mul; + meth->field_sqr = &ec_GFp_sqr; + meth->field_div = &ec_GFp_div; + meth->field_enc = NULL; + meth->field_dec = NULL; + meth->extra1 = NULL; + meth->extra2 = NULL; + meth->extra_free = NULL; + + CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; +} + +/* Construct a generic GFMethod for arithmetic over binary polynomial + * fields with irreducible irr that has array representation irr_arr (see + * ecl-priv.h for description of the representation). If irr_arr is NULL, + * then it is constructed from the bitstring representation. */ +GFMethod * +GFMethod_consGF2m(const mp_int *irr, const unsigned int irr_arr[5]) +{ + mp_err res = MP_OKAY; + int ret; + GFMethod *meth = NULL; + + meth = GFMethod_new(); + if (meth == NULL) + return NULL; + + MP_CHECKOK(mp_copy(irr, &meth->irr)); + if (irr_arr != NULL) { + /* Irreducible polynomials are either trinomials or pentanomials. */ + meth->irr_arr[0] = irr_arr[0]; + meth->irr_arr[1] = irr_arr[1]; + meth->irr_arr[2] = irr_arr[2]; + if (irr_arr[2] > 0) { + meth->irr_arr[3] = irr_arr[3]; + meth->irr_arr[4] = irr_arr[4]; + } else { + meth->irr_arr[3] = meth->irr_arr[4] = 0; + } + } else { + ret = mp_bpoly2arr(irr, meth->irr_arr, 5); + /* Irreducible polynomials are either trinomials or pentanomials. */ + if ((ret != 5) && (ret != 3)) { + res = MP_UNDEF; + goto CLEANUP; + } + } + meth->field_add = &ec_GF2m_add; + meth->field_neg = &ec_GF2m_neg; + meth->field_sub = &ec_GF2m_add; + meth->field_mod = &ec_GF2m_mod; + meth->field_mul = &ec_GF2m_mul; + meth->field_sqr = &ec_GF2m_sqr; + meth->field_div = &ec_GF2m_div; + meth->field_enc = NULL; + meth->field_dec = NULL; + meth->extra1 = NULL; + meth->extra2 = NULL; + meth->extra_free = NULL; + + CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; +} + +/* Free the memory allocated (if any) to a GFMethod object. */ +void +GFMethod_free(GFMethod *meth) +{ + if (meth == NULL) + return; + if (meth->constructed == MP_NO) + return; + if (meth->extra_free != NULL) + meth->extra_free(meth); + free(meth); +} + +/* Wrapper functions for generic prime field arithmetic. */ + +/* Add two field elements. Assumes that 0 <= a, b < meth->irr */ +mp_err +ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */ + mp_err res; + + if ((res = mp_add(a, b, r)) != MP_OKAY) { + return res; + } + if (mp_cmp(r, &meth->irr) >= 0) { + return mp_sub(r, &meth->irr, r); + } + return res; +} + +/* Negates a field element. Assumes that 0 <= a < meth->irr */ +mp_err +ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */ + + if (mp_cmp_z(a) == 0) { + mp_zero(r); + return MP_OKAY; + } + return mp_sub(&meth->irr, a, r); +} + +/* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */ +mp_err +ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + mp_err res = MP_OKAY; + + /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */ + res = mp_sub(a, b, r); + if (res == MP_RANGE) { + MP_CHECKOK(mp_sub(b, a, r)); + if (mp_cmp_z(r) < 0) { + MP_CHECKOK(mp_add(r, &meth->irr, r)); + } + MP_CHECKOK(ec_GFp_neg(r, r, meth)); + } + if (mp_cmp_z(r) < 0) { + MP_CHECKOK(mp_add(r, &meth->irr, r)); + } + CLEANUP: + return res; +} + +/* Reduces an integer to a field element. */ +mp_err +ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + return mp_mod(a, &meth->irr, r); +} + +/* Multiplies two field elements. */ +mp_err +ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + return mp_mulmod(a, b, &meth->irr, r); +} + +/* Squares a field element. */ +mp_err +ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + return mp_sqrmod(a, &meth->irr, r); +} + +/* Divides two field elements. If a is NULL, then returns the inverse of + * b. */ +mp_err +ec_GFp_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_mulmod(a, &t, &meth->irr, r)); + CLEANUP: + mp_clear(&t); + return res; + } +} + +/* Wrapper functions for generic binary polynomial field arithmetic. */ + +/* Adds two field elements. */ +mp_err +ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + return mp_badd(a, b, r); +} + +/* Negates a field element. Note that for binary polynomial fields, the + * negation of a field element is the field element itself. */ +mp_err +ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + if (a == r) { + return MP_OKAY; + } else { + return mp_copy(a, r); + } +} + +/* Reduces a binary polynomial to a field element. */ +mp_err +ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + return mp_bmod(a, meth->irr_arr, r); +} + +/* Multiplies two field elements. */ +mp_err +ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + return mp_bmulmod(a, b, meth->irr_arr, r); +} + +/* Squares a field element. */ +mp_err +ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) +{ + return mp_bsqrmod(a, meth->irr_arr, r); +} + +/* Divides two field elements. If a is NULL, then returns the inverse of + * b. */ +mp_err +ec_GF2m_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) { + /* The GF(2^m) portion of MPI doesn't support invmod, so we + * compute 1/b. */ + MP_CHECKOK(mp_init(&t)); + MP_CHECKOK(mp_set_int(&t, 1)); + MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r)); + CLEANUP: + mp_clear(&t); + return res; + } else { + return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r); + } +} diff --git a/security/nss/lib/freebl/ecl/ecl_mult.c b/security/nss/lib/freebl/ecl/ecl_mult.c new file mode 100644 index 000000000..9609733de --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_mult.c @@ -0,0 +1,359 @@ +/* + * 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): + * 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. + * + */ + +#include "mpi.h" +#include "mplogic.h" +#include "ecl.h" +#include "ecl-priv.h" +#include <stdlib.h> +#include <strings.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]; + mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 4 * 4 * 2], *t; + 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 */ + t = precomp_arr; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + /* x co-ord */ + MP_SIGN(&precomp[i][j][0]) = MP_ZPOS; + MP_ALLOC(&precomp[i][j][0]) = ECL_MAX_FIELD_SIZE_DIGITS; + MP_USED(&precomp[i][j][0]) = 1; + *t = 0; + MP_DIGITS(&precomp[i][j][0]) = t; + t += ECL_MAX_FIELD_SIZE_DIGITS; + /* y co-ord */ + MP_SIGN(&precomp[i][j][1]) = MP_ZPOS; + MP_ALLOC(&precomp[i][j][1]) = ECL_MAX_FIELD_SIZE_DIGITS; + MP_USED(&precomp[i][j][1]) = 1; + *t = 0; + MP_DIGITS(&precomp[i][j][1]) = t; + t += 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: + 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) { + return group->points_mul(k1p, k2p, px, py, rx, ry, group); + } else { + return ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); + } + + CLEANUP: + if (k1 != k1p) { + mp_clear(&k1t); + } + if (k2 != k2p) { + mp_clear(&k2t); + } + return res; +} diff --git a/security/nss/lib/freebl/ecl/ecp.h b/security/nss/lib/freebl/ecl/ecp.h new file mode 100644 index 000000000..801c83c56 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp.h @@ -0,0 +1,136 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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); + +#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_ */ diff --git a/security/nss/lib/freebl/ecl/ecp_192.c b/security/nss/lib/freebl/ecl/ecp_192.c new file mode 100644 index 000000000..914349e63 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_192.c @@ -0,0 +1,228 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#include "ecp.h" +#include "mpi.h" +#include "mplogic.h" +#include "mpi-priv.h" +#include <stdlib.h> + +/* 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); + + /* s is a statically-allocated mp_int of exactly the size we need */ + mp_int s; + +#ifdef ECL_THIRTY_TWO_BIT + mp_digit sa[6]; + mp_digit a11 = 0, a10, a9 = 0, a8, a7 = 0, a6; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 6; + MP_USED(&s) = 6; + MP_DIGITS(&s) = sa; +#else + mp_digit sa[3]; + mp_digit a5 = 0, a4 = 0, a3 = 0; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 3; + MP_USED(&s) = 3; + MP_DIGITS(&s) = sa; +#endif + + /* reduction not needed if a is not larger than field size */ +#ifdef ECL_THIRTY_TWO_BIT + if (a_used < 6) { +#else + if (a_used < 3) { +#endif + return mp_copy(a, r); + } +#ifdef ECL_THIRTY_TWO_BIT + /* for polynomials larger than twice the field size, use regular + * reduction */ + if (a_used > 12) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + 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); + case 8: + a7 = MP_DIGIT(a, 7); + case 7: + a6 = MP_DIGIT(a, 6); + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 7)); + MP_DIGIT(r, 5) = MP_DIGIT(a, 5); + MP_DIGIT(r, 4) = MP_DIGIT(a, 4); + MP_DIGIT(r, 3) = MP_DIGIT(a, 3); + MP_DIGIT(r, 2) = MP_DIGIT(a, 2); + MP_DIGIT(r, 1) = MP_DIGIT(a, 1); + MP_DIGIT(r, 0) = MP_DIGIT(a, 0); + } + MP_USED(r) = 6; + /* compute r = s1 + s2 + s3 + s4, where s1 = (a2,a1,a0), s2 = + * (0,a3,a3), s3 = (a4,a4,0), and s4 = (a5,a5,a5), for + * sixty-four-bit words */ + switch (a_used) { + case 12: + case 11: + sa[5] = sa[3] = sa[1] = a11; + sa[4] = sa[2] = sa[0] = a10; + MP_CHECKOK(mp_add(r, &s, r)); + case 10: + case 9: + sa[5] = sa[3] = a9; + sa[4] = sa[2] = a8; + sa[1] = sa[0] = 0; + MP_CHECKOK(mp_add(r, &s, r)); + case 8: + case 7: + sa[5] = sa[4] = 0; + sa[3] = sa[1] = a7; + sa[2] = sa[0] = a6; + MP_CHECKOK(mp_add(r, &s, r)); + } + /* there might be 1 or 2 bits left to reduce; use regular + * reduction for this */ + MP_CHECKOK(mp_mod(r, &meth->irr, r)); + } +#else + /* for polynomials larger than twice the field size, use regular + * reduction */ + if (a_used > 6) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + case 6: + a5 = MP_DIGIT(a, 5); + case 5: + a4 = MP_DIGIT(a, 4); + case 4: + a3 = MP_DIGIT(a, 3); + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 4)); + MP_DIGIT(r, 2) = MP_DIGIT(a, 2); + MP_DIGIT(r, 1) = MP_DIGIT(a, 1); + MP_DIGIT(r, 0) = MP_DIGIT(a, 0); + } + MP_USED(r) = 3; + /* compute r = s1 + s2 + s3 + s4, where s1 = (a2,a1,a0), s2 = + * (0,a3,a3), s3 = (a4,a4,0), and s4 = (a5,a5,a5) */ + switch (a_used) { + case 6: + sa[2] = sa[1] = sa[0] = a5; + MP_CHECKOK(mp_add(r, &s, r)); + case 5: + sa[2] = sa[1] = a4; + sa[0] = 0; + MP_CHECKOK(mp_add(r, &s, r)); + case 4: + sa[2] = 0; + sa[1] = sa[0] = a3; + MP_CHECKOK(mp_add(r, &s, r)); + } + /* there might be 1 or 2 bits left to reduce; use regular + * reduction for this */ + MP_CHECKOK(mp_mod(r, &meth->irr, r)); + } +#endif + + CLEANUP: + return res; +} + +/* 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; +} + +/* 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; + } + return MP_OKAY; +} diff --git a/security/nss/lib/freebl/ecl/ecp_224.c b/security/nss/lib/freebl/ecl/ecp_224.c new file mode 100644 index 000000000..6e6e81ce4 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_224.c @@ -0,0 +1,305 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#include "ecp.h" +#include "mpi.h" +#include "mplogic.h" +#include "mpi-priv.h" +#include <stdlib.h> + +/* 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); + + /* s is a statically-allocated mp_int of exactly the size we need */ + mp_int s; + +#ifdef ECL_THIRTY_TWO_BIT + mp_digit sa[8]; + mp_digit a13 = 0, a12 = 0, a11 = 0, a10, a9 = 0, a8, a7; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 8; + MP_USED(&s) = 7; + MP_DIGITS(&s) = sa; +#else + mp_digit sa[4]; + mp_digit a6 = 0, a5 = 0, a4 = 0, a3 = 0; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 4; + MP_USED(&s) = 4; + MP_DIGITS(&s) = sa; +#endif + + /* reduction not needed if a is not larger than field size */ +#ifdef ECL_THIRTY_TWO_BIT + if (a_used < 8) { +#else + if (a_used < 4) { +#endif + return mp_copy(a, r); + } +#ifdef ECL_THIRTY_TWO_BIT + /* for polynomials larger than twice the field size, use regular + * reduction */ + if (a_used > 14) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + 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); + case 8: + a7 = MP_DIGIT(a, 7); + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 8)); + MP_DIGIT(r, 6) = MP_DIGIT(a, 6); + MP_DIGIT(r, 5) = MP_DIGIT(a, 5); + MP_DIGIT(r, 4) = MP_DIGIT(a, 4); + MP_DIGIT(r, 3) = MP_DIGIT(a, 3); + MP_DIGIT(r, 2) = MP_DIGIT(a, 2); + MP_DIGIT(r, 1) = MP_DIGIT(a, 1); + MP_DIGIT(r, 0) = MP_DIGIT(a, 0); + } + MP_USED(r) = 7; + switch (a_used) { + case 14: + case 13: + case 12: + case 11: + sa[6] = a10; + case 10: + sa[5] = a9; + case 9: + sa[4] = a8; + case 8: + sa[3] = a7; + sa[2] = sa[1] = sa[0] = 0; + MP_USED(&s) = a_used - 4; + if (MP_USED(&s) > 7) + MP_USED(&s) = 7; + MP_CHECKOK(mp_add(r, &s, r)); + } + switch (a_used) { + case 14: + sa[5] = a13; + case 13: + sa[4] = a12; + case 12: + sa[3] = a11; + sa[2] = sa[1] = sa[0] = 0; + MP_USED(&s) = a_used - 8; + MP_CHECKOK(mp_add(r, &s, r)); + } + switch (a_used) { + case 14: + sa[6] = a13; + case 13: + sa[5] = a12; + case 12: + sa[4] = a11; + case 11: + sa[3] = a10; + case 10: + sa[2] = a9; + case 9: + sa[1] = a8; + case 8: + sa[0] = a7; + MP_USED(&s) = a_used - 7; + MP_CHECKOK(mp_sub(r, &s, r)); + } + switch (a_used) { + case 14: + sa[2] = a13; + case 13: + sa[1] = a12; + case 12: + sa[0] = a11; + MP_USED(&s) = a_used - 11; + MP_CHECKOK(mp_sub(r, &s, r)); + } + /* there might be 1 or 2 bits left to reduce; use regular + * reduction for this */ + MP_CHECKOK(mp_mod(r, &meth->irr, r)); + } +#else + /* for polynomials larger than twice the field size, use regular + * reduction */ + if (a_used > 7) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + case 7: + a6 = MP_DIGIT(a, 6); + case 6: + a5 = MP_DIGIT(a, 5); + case 5: + a4 = MP_DIGIT(a, 4); + case 4: + a3 = MP_DIGIT(a, 3) >> 32; + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 5)); + MP_DIGIT(r, 3) = MP_DIGIT(a, 3) & 0xFFFFFFFF; + MP_DIGIT(r, 2) = MP_DIGIT(a, 2); + MP_DIGIT(r, 1) = MP_DIGIT(a, 1); + MP_DIGIT(r, 0) = MP_DIGIT(a, 0); + } else { + MP_DIGIT(r, 3) &= 0xFFFFFFFF; + } + MP_USED(r) = 4; + switch (a_used) { + case 7: + case 6: + sa[3] = a5 & 0xFFFFFFFF; + case 5: + sa[2] = a4; + case 4: + sa[1] = a3 << 32; + sa[0] = 0; + MP_USED(&s) = a_used - 2; + if (MP_USED(&s) == 5) + MP_USED(&s) = 4; + MP_CHECKOK(mp_add(r, &s, r)); + } + switch (a_used) { + case 7: + sa[2] = a6; + case 6: + sa[1] = (a5 >> 32) << 32; + sa[0] = 0; + MP_USED(&s) = a_used - 4; + MP_CHECKOK(mp_add(r, &s, r)); + } + sa[2] = sa[1] = sa[0] = 0; + switch (a_used) { + case 7: + sa[3] = a6 >> 32; + sa[2] = a6 << 32; + case 6: + sa[2] |= a5 >> 32; + sa[1] = a5 << 32; + case 5: + sa[1] |= a4 >> 32; + sa[0] = a4 << 32; + case 4: + sa[0] |= a3; + MP_USED(&s) = a_used - 3; + MP_CHECKOK(mp_sub(r, &s, r)); + } + sa[0] = 0; + switch (a_used) { + case 7: + sa[1] = a6 >> 32; + sa[0] = a6 << 32; + case 6: + sa[0] |= a5 >> 32; + MP_USED(&s) = a_used - 5; + MP_CHECKOK(mp_sub(r, &s, r)); + } + /* there might be 1 or 2 bits left to reduce; use regular + * reduction for this */ + MP_CHECKOK(mp_mod(r, &meth->irr, r)); + } +#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; +} + +/* 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; + } + return MP_OKAY; +} diff --git a/security/nss/lib/freebl/ecl/ecp_aff.c b/security/nss/lib/freebl/ecl/ecp_aff.c new file mode 100644 index 000000000..0bda87657 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_aff.c @@ -0,0 +1,284 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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 diff --git a/security/nss/lib/freebl/ecl/ecp_fp.c b/security/nss/lib/freebl/ecl/ecp_fp.c new file mode 100644 index 000000000..1b9c6ed67 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp.c @@ -0,0 +1,566 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_fp.h b/security/nss/lib/freebl/ecl/ecp_fp.h new file mode 100644 index 000000000..6df7b9e69 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp.h @@ -0,0 +1,405 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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 diff --git a/security/nss/lib/freebl/ecl/ecp_fp160.c b/security/nss/lib/freebl/ecl/ecp_fp160.c new file mode 100644 index 000000000..57399d494 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp160.c @@ -0,0 +1,178 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_fp192.c b/security/nss/lib/freebl/ecl/ecp_fp192.c new file mode 100644 index 000000000..2e143aa49 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp192.c @@ -0,0 +1,176 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_fp224.c b/security/nss/lib/freebl/ecl/ecp_fp224.c new file mode 100644 index 000000000..f32e8d717 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp224.c @@ -0,0 +1,189 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_fpinc.c b/security/nss/lib/freebl/ecl/ecp_fpinc.c new file mode 100644 index 000000000..e05e478ef --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fpinc.c @@ -0,0 +1,854 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +/* 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); + } +} diff --git a/security/nss/lib/freebl/ecl/ecp_jac.c b/security/nss/lib/freebl/ecl/ecp_jac.c new file mode 100644 index 000000000..8eea8c904 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_jac.c @@ -0,0 +1,553 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_jm.c b/security/nss/lib/freebl/ecl/ecp_jm.c new file mode 100644 index 000000000..2174650d1 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_jm.c @@ -0,0 +1,320 @@ +/* + * 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 Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. 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. + * + */ + +#include "ecp.h" +#include "ecl-priv.h" +#include "mplogic.h" +#include <stdlib.h> + +/* 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, 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)); + + /* 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, rz, group->meth)); + MP_CHECKOK(group->meth->field_add(rz, rz, 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, ry, group->meth)); + MP_CHECKOK(group->meth->field_mul(ry, &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: + mp_clear(&t0); + mp_clear(&t1); + mp_clear(&M); + mp_clear(&S); + 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, 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)); + 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: + mp_clear(&A); + mp_clear(&B); + mp_clear(&C); + mp_clear(&D); + mp_clear(&C2); + mp_clear(&C3); + 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; + 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; + } + + 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])); + } + + /* 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); + 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, 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, group); + } + } + + /* convert result S to affine coordinates */ + MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); + + CLEANUP: + 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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_mont.c b/security/nss/lib/freebl/ecl/ecp_mont.c new file mode 100644 index 000000000..a251af1fc --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_mont.c @@ -0,0 +1,190 @@ +/* + * 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): + * 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. + * + */ + +/* 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; + } +} diff --git a/security/nss/lib/freebl/mpi/mp_gf2m-priv.h b/security/nss/lib/freebl/mpi/mp_gf2m-priv.h new file mode 100644 index 000000000..e2236299f --- /dev/null +++ b/security/nss/lib/freebl/mpi/mp_gf2m-priv.h @@ -0,0 +1,101 @@ +/* + * 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 Multi-precision Binary Polynomial Arithmetic + * 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): + * Sheueling Chang Shantz <sheueling.chang@sun.com> and + * Douglas Stebila <douglas@stebila.ca> of Sun 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. + * + */ + +#ifndef _MP_GF2M_PRIV_H_ +#define _MP_GF2M_PRIV_H_ + +#include "mpi-priv.h" + +extern const mp_digit mp_gf2m_sqr_tb[16]; + +#if defined(MP_USE_UINT_DIGIT) +#define MP_DIGIT_BITS 32 +#else +#define MP_DIGIT_BITS 64 +#endif + +/* Platform-specific macros for fast binary polynomial squaring. */ +#if MP_DIGIT_BITS == 32 +#define gf2m_SQR1(w) \ + mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] +#define gf2m_SQR0(w) \ + mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF] +#else +#define gf2m_SQR1(w) \ + mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \ + mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \ + mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF] +#define gf2m_SQR0(w) \ + mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \ + mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \ + mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF] +#endif + +/* Multiply two binary polynomials mp_digits a, b. + * Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1. + * Output in two mp_digits rh, rl. + */ +void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b); + +/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0) + * result is a binary polynomial in 4 mp_digits r[4]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1, + const mp_digit b0); + +/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0) + * result is a binary polynomial in 6 mp_digits r[6]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0, + const mp_digit b2, const mp_digit b1, const mp_digit b0); + +/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0) + * result is a binary polynomial in 8 mp_digits r[8]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1, + const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1, + const mp_digit b0); + +#endif /* _MP_GF2M_PRIV_H_ */ diff --git a/security/nss/lib/freebl/mpi/target.mk b/security/nss/lib/freebl/mpi/target.mk new file mode 100644 index 000000000..ee175d2a4 --- /dev/null +++ b/security/nss/lib/freebl/mpi/target.mk @@ -0,0 +1,220 @@ +## 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 Michael J. Fromberger are +## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved. +## +## Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +## Sun Microsystems, Inc. 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 the GNU General Public License Version 2 or later (the +## "GPL"), in which case the provisions of the GPL are applicable +## instead of those above. If you wish to allow use of your +## version of this file only under the terms of the GPL and not to +## allow others to use your version of this file under the MPL, +## indicate your decision by deleting the provisions above and +## replace them with the notice and other provisions required by +## the GPL. If you do not delete the provisions above, a recipient +## may use your version of this file under either the MPL or the +## GPL. +## + +## +## 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 +CFLAGS= -O $(MPICMN) +#CFLAGS=-ansi -fullwarn -woff 1521 -O3 $(MPICMN) +#CFLAGS=-ansi -pedantic -Wall -O3 $(MPICMN) +#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1 $(MPICMN) + +ifeq ($(TARGET),mipsIRIX) +#IRIX +#MPICMN += -DMP_MONT_USE_MP_MUL +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +MPICMN += -DMP_USE_UINT_DIGIT +#MPICMN += -DMP_NO_MP_WORD +AS_OBJS = mpi_mips.o +#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions +ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 +#CFLAGS=-ansi -n32 -O3 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +CFLAGS=-ansi -n32 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +#CFLAGS=-ansi -64 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \ + $(MPICMN) +endif + +ifeq ($(TARGET),alphaOSF1) +#Alpha/OSF1 +MPICMN += -DMP_ASSEMBLY_MULTIPLY +AS_OBJS+= mpvalpha.o +#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT $(MPICMN) +CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT \ + -DMP_NO_MP_WORD $(MPICMN) +endif + +ifeq ($(TARGET),v9SOLARIS) +#Solaris 64 +SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt +#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v9a -KPIC -mt +SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v9a -KPIC -mt +AS_OBJS += montmulfv9.o +AS_OBJS += mpi_sparc.o mpv_sparcv9.o +MPICMN += -DMP_USE_UINT_DIGIT +#MPICMN += -DMP_NO_MP_WORD +MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USING_MONT_MULF +CFLAGS= -O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN) +#CFLAGS= -g -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),v8plusSOLARIS) +#Solaris 32 +SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8plusa -KPIC -mt +SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt +AS_OBJS += montmulfv8.o +AS_OBJS += mpi_sparc.o mpv_sparcv8.o +#AS_OBJS = montmulf.o +MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USING_MONT_MULF +MPICMN += -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_MP_WORD +CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_6 -xarch=v8plus -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),v8SOLARIS) +#Solaris 32 +#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8 -KPIC -mt +#SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt +#AS_OBJS = montmulfv8.o mpi_sparc.o mpv_sparcv8.o +#AS_OBJS = montmulf.o +#MPICMN += -DMP_USING_MONT_MULF +#MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_MP_WORD +CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_6 -xarch=v8 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),ia64HPUX) +#HPUX 32 on ia64 -- 64 bit digits SCREAM. +# This one is for DD32 which is the 32-bit ABI with 64-bit registers. +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +endif + +ifeq ($(TARGET),ia64HPUX64) +#HPUX 32 on ia64 +# This one is for DD64 which is the 64-bit ABI +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +endif + +ifeq ($(TARGET),PA2.0WHPUX) +#HPUX64 (HP PA 2.0 Wide) using MAXPY and 64-bit digits +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +AS_OBJS = mpi_hp.o hpma512.o hppa20.o +CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +O3 +DChpux -DHPUX11 -DXP_UNIX \ + $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + $(MPICMN) +AS = $(CC) $(CFLAGS) -c +endif + +ifeq ($(TARGET),PA2.0NHPUX) +#HPUX32 (HP PA 2.0 Narrow) hybrid model, using 32-bit digits +# This one is for DA2.0 (N) which is the 32-bit ABI with 64-bit registers. +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +AS_OBJS = mpi_hp.o hpma512.o hppa20.o +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + -Wl,+k $(MPICMN) +AS = $(CC) $(CFLAGS) -c +endif + +ifeq ($(TARGET),PA1.1HPUX) +#HPUX32 (HP PA 1.1) Pure 32 bit +MPICMN += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD +#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY +CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) +##CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ +# -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),32AIX) +# +CC = xlC_r +MPICMN += -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_DIV_WORD +#MPICMN += -DMP_NO_MUL_WORD +MPICMN += -DMP_NO_ADD_WORD +MPICMN += -DMP_NO_SUB_WORD +#MPICMN += -DMP_NO_MP_WORD +#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY +CFLAGS = -O -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +#CFLAGS = -g -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +#CFLAGS += -pg +endif + +ifeq ($(TARGET),64AIX) +# +CC = xlC_r +MPICMN += -DMP_USE_UINT_DIGIT +CFLAGS = -O -O2 -DAIX -DSYSV -qarch=com -DAIX_64BIT -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +OBJECT_MODE=64 +export OBJECT_MODE +endif + +ifeq ($(TARGET),x86LINUX) +#Linux +AS_OBJS = mpi_x86.o +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D +MPICMN += -DMP_MONT_USE_MP_MUL +CFLAGS= -O2 -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) +#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -DDEBUG -UNDEBUG -D_REENTRANT $(MPICMN) +#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) +endif diff --git a/security/nss/tests/cert/eccert.sh b/security/nss/tests/cert/eccert.sh new file mode 100644 index 000000000..026f8827a --- /dev/null +++ b/security/nss/tests/cert/eccert.sh @@ -0,0 +1,889 @@ +#! /bin/sh +# +# 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. +# +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +######################################################################## +# +# mozilla/security/nss/tests/cert/rcert.sh +# +# Certificate generating and handeling for NSS QA, can be included +# multiple times from all.sh and the individual scripts +# +# needs to work on all Unix and Windows platforms +# +# included from (don't expect this to be up to date) +# -------------------------------------------------- +# all.sh +# ssl.sh +# smime.sh +# tools.sh +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +# FIXME - Netscape - NSS +######################################################################## + +############################## cert_init ############################### +# local shell function to initialize this script +######################################################################## +cert_init() +{ + SCRIPTNAME="cert.sh" + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + if [ -z "${INIT_SOURCED}" ] ; then + cd ../common + . ./init.sh + fi + SCRIPTNAME="cert.sh" + html_head "Certutil Tests" + + ################## Generate noise for our CA cert. ###################### + # NOTE: these keys are only suitable for testing, as this whole thing + # bypasses the entropy gathering. Don't use this method to generate + # keys and certs for product use or deployment. + # + ps -efl > ${NOISE_FILE} 2>&1 + ps aux >> ${NOISE_FILE} 2>&1 + noise + +} + +cert_log() ###################### write the cert_status file +{ + echo "$SCRIPTNAME $*" + echo $* >>${CERT_LOG_FILE} +} + +################################ noise ################################## +# Generate noise for our certs +# +# NOTE: these keys are only suitable for testing, as this whole thing bypasses +# the entropy gathering. Don't use this method to generate keys and certs for +# product use or deployment. +######################################################################### +noise() +{ + #netstat >> ${NOISE_FILE} 2>&1 + date >> ${NOISE_FILE} 2>&1 +} + +################################ certu ################################# +# local shell function to call certutil, also: writes action and options to +# stdout, sets variable RET and writes results to the html file results +######################################################################## +certu() +{ + echo "$SCRIPTNAME: ${CU_ACTION} --------------------------" + + if [ -n "${CU_SUBJECT}" ]; then + #the subject of the cert contains blanks, and the shell + #will strip the quotes off the string, if called otherwise... + echo "certutil -s \"${CU_SUBJECT}\" $*" + certutil -s "${CU_SUBJECT}" $* + RET=$? + CU_SUBJECT="" + else + echo "certutil $*" + certutil $* + RET=$? + fi + if [ "$RET" -ne 0 ]; then + CERTFAILED=$RET + html_failed "<TR><TD>${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "<TR><TD>${CU_ACTION}" + fi + + # echo "Contine?" + # cat > /dev/null + return $RET +} + +############################# cert_init_cert ########################## +# local shell function to initialize creation of client and server certs +######################################################################## +cert_init_cert() +{ + CERTDIR="$1" + CERTNAME="$2" + CERTSERIAL="$3" + DOMAIN="$4" + + if [ ! -d "${CERTDIR}" ]; then + mkdir -p "${CERTDIR}" + else + echo "$SCRIPTNAME: WARNING - ${CERTDIR} exists" + fi + cd "${CERTDIR}" + CERTDIR="." + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${DOMAIN}" + fi + + noise +} + +############################# hw_acc ################################# +# local shell function to add hw accelerator modules to the db +######################################################################## +hw_acc() +{ + HW_ACC_RET=0 + HW_ACC_ERR="" + if [ -n "$O_HWACC" -a "$O_HWACC" = ON -a -z "$USE_64" ] ; then + echo "creating $CERTNAME s cert with hwaccelerator..." + #case $ACCELERATOR in + #rainbow) + + + echo "modutil -add rainbow -libfile /usr/lib/libcryptoki22.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add rainbow -libfile /usr/lib/libcryptoki22.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add rainbow failed in `pwd`" + HW_ACC_RET=1 + HW_ACC_ERR="modutil -add rainbow" + fi + + echo "modutil -add ncipher " + echo " -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add ncipher \ + -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add ncipher failed in `pwd`" + HW_ACC_RET=`expr $HW_ACC_RET + 2` + HW_ACC_ERR="$HW_ACC_ERR,modutil -add ncipher" + fi + if [ "$HW_ACC_RET" -ne 0 ]; then + html_failed "<TR><TD>Adding HW accelerators to certDB for ${CERTNAME} ($HW_ACC_RET) " + else + html_passed "<TR><TD>Adding HW accelerators to certDB for ${CERTNAME}" + fi + + fi + return $HW_ACC_RET +} + +############################# cert_create_cert ######################### +# local shell function to create client certs +# initialize DB, import +# root cert +# add cert to DB +######################################################################## +cert_create_cert() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_cert "$5" + return $? +} + +############################# cert_create_certs ######################## +# local shell function to create client certs +# initialize DB, import +# root certs (RSA and EC) +# add certs (RSA and EC) to DB +######################################################################## +cert_create_certs() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + CU_ACTION="Import EC Root CA for $CERTNAME" + certu -A -n "TestCA-ec" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/ecroot.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_certs "$5" + return $? +} + +############################# cert_add_cert ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +######################################################################## +cert_add_cert() +{ + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + return 0 +} + +############################# cert_add_certs ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +# Do this for both RSA and EC certs +######################################################################## +cert_add_certs() +{ + CURVE="secp160r2" + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + +# +# Generate and add EC cert +# + CU_ACTION="Generate EC Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -k ec -q "${CURVE}" -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s EC Request" + certu -C -c "TestCA-ec" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's EC Cert" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's EC Cert Created" + + return 0 +} + +################################# cert_all_CA ################################ +# local shell function to build the additional Temp. Certificate Authority (CA) +# used for the "real life" ssl test with 2 different CA's in the +# client and in teh server's dir +########################################################################## +cert_all_CA() +{ + CA_CURVE="secp160r1" + + echo nss > ${PWFILE} + + ALL_CU_SUBJECT="CN=NSS Test CA, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_CA $CADIR TestCA -x "CTu,CTu,CTu" ${D_CA} "1" + +# Create EC version of TestCA + ALL_CU_SUBJECT="CN=NSS Test CA (ECC), O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_ec_CA $CADIR TestCA-ec -x "CTu,CTu,CTu" ${D_CA} "1" ${CA_CURVE} + + ALL_CU_SUBJECT="CN=NSS Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" ${D_SERVER_CA} "3" + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" ${D_SERVER_CA} "4" + +# +# Create EC versions of the above CA certs +# + ALL_CU_SUBJECT="CN=NSS Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR serverCA-ec -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR chain-1-serverCA-ec "-c serverCA-ec" "u,u,u" ${D_SERVER_CA} "3" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR chain-2-serverCA-ec "-c chain-1-serverCA-ec" "u,u,u" ${D_SERVER_CA} "4" ${CA_CURVE} + + + ALL_CU_SUBJECT="CN=NSS Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" ${D_CLIENT_CA} "6" + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" ${D_CLIENT_CA} "7" + +# +# Create EC versions of the above CA certs +# + ALL_CU_SUBJECT="CN=NSS Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR clientCA-ec -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR chain-1-clientCA-ec "-c clientCA-ec" "u,u,u" ${D_CLIENT_CA} "6" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR chain-2-clientCA-ec "-c chain-1-clientCA-ec" "u,u,u" ${D_CLIENT_CA} "7" ${CA_CURVE} + + rm $CLIENT_CADIR/root.cert $SERVER_CADIR/root.cert + rm $CLIENT_CADIR/ecroot.cert $SERVER_CADIR/ecroot.cert + # root.cert in $CLIENT_CADIR and in $SERVER_CADIR is the one of the last + # in the chain +} + +################################# cert_CA ################################ +# local shell function to build the Temp. Certificate Authority (CA) +# used for testing purposes, creating a CA Certificate and a root cert +########################################################################## +cert_CA() +{ + CUR_CADIR=$1 + NICKNAME=$2 + SIGNER=$3 + TRUSTARG=$4 + DOMAIN=$5 + CERTSERIAL=$6 + + echo "$SCRIPTNAME: Creating a CA Certificate $NICKNAME ==========================" + + if [ ! -d "${CUR_CADIR}" ]; then + mkdir -p "${CUR_CADIR}" + fi + cd ${CUR_CADIR} + pwd + + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi + + if [ "$SIGNER" = "-x" ] ; then # self signed -> create DB + CU_ACTION="Creating CA Cert DB" + certu -N -d ${LPROFILE} -f ${R_PWFILE} 2>&1 + if [ "$RET" -ne 0 ]; then + Exit 5 "Fatal - failed to create CA $NICKNAME " + fi + echo "$SCRIPTNAME: Certificate initialized ----------" + fi + + + ################# Creating CA Cert ###################################### + # + CU_ACTION="Creating CA Cert $NICKNAME " + CU_SUBJECT=$ALL_CU_SUBJECT + certu -S -n $NICKNAME -t $TRUSTARG -v 60 $SIGNER -d ${LPROFILE} -1 -2 -5 \ + -f ${R_PWFILE} -z ${R_NOISE_FILE} -m $CERTSERIAL 2>&1 <<CERTSCRIPT +5 +9 +n +y +-1 +n +5 +6 +7 +9 +n +CERTSCRIPT + + if [ "$RET" -ne 0 ]; then + echo "return value is $RET" + Exit 6 "Fatal - failed to create CA cert" + fi + + ################# Exporting Root Cert ################################### + # + CU_ACTION="Exporting Root Cert" + certu -L -n $NICKNAME -r -d ${LPROFILE} -o root.cert + if [ "$RET" -ne 0 ]; then + Exit 7 "Fatal - failed to export root cert" + fi + cp root.cert ${NICKNAME}.ca.cert +} + +################################ cert_ec_CA ############################## +# local shell function to build the Temp. Certificate Authority (CA) +# used for testing purposes, creating a CA Certificate and a root cert +# This is the ECC version of cert_CA. +########################################################################## +cert_ec_CA() +{ + CUR_CADIR=$1 + NICKNAME=$2 + SIGNER=$3 + TRUSTARG=$4 + DOMAIN=$5 + CERTSERIAL=$6 + CURVE=$7 + + echo "$SCRIPTNAME: Creating an EC CA Certificate $NICKNAME ==========================" + + if [ ! -d "${CUR_CADIR}" ]; then + mkdir -p "${CUR_CADIR}" + fi + cd ${CUR_CADIR} + pwd + + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi + + ################# Creating an EC CA Cert ################################ + # + CU_ACTION="Creating EC CA Cert $NICKNAME " + CU_SUBJECT=$ALL_CU_SUBJECT + certu -S -n $NICKNAME -k ec -q $CURVE -t $TRUSTARG -v 60 $SIGNER \ + -d ${LPROFILE} -1 -2 -5 -f ${R_PWFILE} -z ${R_NOISE_FILE} \ + -m $CERTSERIAL 2>&1 <<CERTSCRIPT +5 +9 +n +y +-1 +n +5 +6 +7 +9 +n +CERTSCRIPT + + if [ "$RET" -ne 0 ]; then + echo "return value is $RET" + Exit 6 "Fatal - failed to create EC CA cert" + fi + + ################# Exporting EC Root Cert ################################ + # + CU_ACTION="Exporting EC Root Cert" + certu -L -n $NICKNAME -r -d ${LPROFILE} -o ecroot.cert + if [ "$RET" -ne 0 ]; then + Exit 7 "Fatal - failed to export ec root cert" + fi + cp ecroot.cert ${NICKNAME}.ca.cert +} + +############################## cert_smime_client ############################# +# local shell function to create client Certificates for S/MIME tests +############################################################################## +cert_smime_client() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ==============" + + cert_create_certs ${ALICEDIR} "Alice" 30 ${D_ALICE} + cert_create_cert ${BOBDIR} "Bob" 40 ${D_BOB} + + echo "$SCRIPTNAME: Creating Dave's Certificate -------------------------" + cert_create_cert "${DAVEDIR}" Dave 50 ${D_DAVE} + + echo "$SCRIPTNAME: Creating multiEmail's Certificate --------------------" + cert_create_cert "${EVEDIR}" "Eve" 60 ${D_EVE} "-7 eve@bogus.net,eve@bogus.cc,beve@bogus.com" + + #echo "************* Copying CA files to ${SERVERDIR}" + #cp ${CADIR}/*.db . + #hw_acc + + ######################################################################### + # + #cd ${CERTDIR} + #CU_ACTION="Creating ${CERTNAME}'s Server Cert" + #CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" + #certu -S -n "${CERTNAME}" -c "TestCA" -t "u,u,u" -m "$CERTSERIAL" \ + # -d ${PROFILEDIR} -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + #CU_ACTION="Export Dave's Cert" + #cd ${DAVEDIR} + #certu -L -n "Dave" -r -d ${P_R_DAVE} -o Dave.cert + + ################# Importing Certificates for S/MIME tests ############### + # + echo "$SCRIPTNAME: Importing Certificates ==============================" + CU_ACTION="Import Alices's cert into Bob's db" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_ALICEDIR}/Alice.cert 2>&1 + + CU_ACTION="Import Bob's cert into Alice's db" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_BOBDIR}/Bob.cert 2>&1 + + CU_ACTION="Import Dave's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Dave's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Eve's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + CU_ACTION="Import Eve's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SMIME failed $RET" + else + cert_log "SUCCESS: SMIME passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for extended SSL test +######################################################################## +cert_extended_ssl() +{ + EC_CURVE="sect163r1" + + ################# Creating Certs for extended SSL test #################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Certificates, issued by the last ===============" + echo " of a chain of CA's which are not in the same database============" + + echo "Server Cert" + cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 ${D_EXT_SERVER} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + + CU_ACTION="Import Client Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 +# +# Repeat the above for EC certs +# + CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s EC Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA-ec" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's EC Cert -t u,u,u (ext)" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + + CU_ACTION="Import Client EC Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA-ec" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA-ec.ca.cert" 2>&1 +# +# done with EC certs +# + echo "Importing all the server's own CA chain into the servers DB" + for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "serverCA" ] ; then + T="-t C,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.) " + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done +#============ + echo "Client Cert" + cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 ${D_EXT_CLIENT} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + CU_ACTION="Import Server Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA.ca.cert" 2>&1 +# +# Repeat the above for EC certs +# + CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s EC Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA-ec" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's EC Cert -t u,u,u (ext)" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + CU_ACTION="Import Server EC Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA-ec" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA-ec.ca.cert" 2>&1 +# +# done with EC certs +# + echo "Importing all the client's own CA chain into the servers DB" + for CA in `find ${CLIENT_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "clientCA" ] ; then + T="-t T,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.)" + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: EXT failed $RET" + else + cert_log "SUCCESS: EXT passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for SSL test +######################################################################## +cert_ssl() +{ + ################# Creating Certs for SSL test ########################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + cert_create_certs ${CLIENTDIR} "TestUser" 70 ${D_CLIENT} + + echo "$SCRIPTNAME: Creating Server CA Issued Certificate for \\" + echo " ${HOSTADDR} ------------------------------------" + cert_create_certs ${SERVERDIR} "${HOSTADDR}" 100 ${D_SERVER} + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} + certu -M -n "TestCA-ec" -t "TC,TC,TC" -d ${PROFILEDIR} +# cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} +# echo "************* Copying CA files to ${SERVERDIR}" +# cp ${CADIR}/*.db . +# hw_acc +# CU_ACTION="Creating ${CERTNAME}'s Server Cert" +# CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" +# certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d ${PROFILEDIR} \ +# -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SSL failed $RET" + else + cert_log "SUCCESS: SSL passed" + fi +} +############################## cert_stresscerts ################################ +# local shell function to create client certs for SSL stresstest +######################################################################## +cert_stresscerts() +{ + + ############### Creating Certs for SSL stress test ####################### + # + CERTDIR="$CLIENTDIR" + cd "${CERTDIR}" + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${D_CLIENT}" + fi + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + + CONTINUE=$GLOB_MAX_CERT + CERTSERIAL=10 + + while [ $CONTINUE -ge $GLOB_MIN_CERT ] + do + CERTNAME="TestUser$CONTINUE" +# cert_add_cert ${CLIENTDIR} "TestUser$CONTINUE" $CERTSERIAL + cert_add_certs + CERTSERIAL=`expr $CERTSERIAL + 1 ` + CONTINUE=`expr $CONTINUE - 1 ` + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: StressCert failed $RET" + else + cert_log "SUCCESS: StressCert passed" + fi +} + +############################## cert_fips ##################################### +# local shell function to create certificates for FIPS tests +############################################################################## +cert_fips() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating FIPS 140-1 DSA Certificates ==============" + cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 "${D_FIPS}" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" 2>&1 + + echo "$SCRIPTNAME: Enable FIPS mode on database -----------------------" + CU_ACTION="Enable FIPS mode on database for ${CERTNAME}" + echo "modutil -dbdir ${PROFILEDIR} -fips true " + modutil -dbdir ${PROFILEDIR} -fips true 2>&1 <<MODSCRIPT +y +MODSCRIPT + RET=$? + if [ "$RET" -ne 0 ]; then + html_failed "<TR><TD>${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "<TR><TD>${CU_ACTION}" + fi + + CU_ACTION="Generate Certificate for ${CERTNAME}" + CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140-1, L=Mountain View, ST=California, C=US" + certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -m 500 -z "${R_NOISE_FILE}" 2>&1 + if [ "$RET" -eq 0 ]; then + cert_log "SUCCESS: FIPS passed" + fi +} + +############################## cert_cleanup ############################ +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +cert_cleanup() +{ + cert_log "$SCRIPTNAME: finished $SCRIPTNAME" + html "</TABLE><BR>" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +cert_init +cert_all_CA +cert_extended_ssl +cert_ssl +cert_smime_client +cert_fips +if [ -n "$DO_DIST_ST" -a "$DO_DIST_ST" = "TRUE" ] ; then + cert_stresscerts + #following lines to be used when databases are to be reused + #cp -r /u/sonmi/tmp/stress/kentuckyderby.13/* $HOSTDIR + #cp -r $HOSTDIR/../${HOST}.2/* $HOSTDIR + +fi +cert_cleanup diff --git a/security/nss/tests/cert/noeccert.sh b/security/nss/tests/cert/noeccert.sh new file mode 100755 index 000000000..6bb91b6a8 --- /dev/null +++ b/security/nss/tests/cert/noeccert.sh @@ -0,0 +1,654 @@ +#! /bin/sh +# +# 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +######################################################################## +# +# mozilla/security/nss/tests/cert/rcert.sh +# +# Certificate generating and handeling for NSS QA, can be included +# multiple times from all.sh and the individual scripts +# +# needs to work on all Unix and Windows platforms +# +# included from (don't expect this to be up to date) +# -------------------------------------------------- +# all.sh +# ssl.sh +# smime.sh +# tools.sh +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +# FIXME - Netscape - NSS +######################################################################## + +############################## cert_init ############################### +# local shell function to initialize this script +######################################################################## +cert_init() +{ + SCRIPTNAME="cert.sh" + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + if [ -z "${INIT_SOURCED}" ] ; then + cd ../common + . ./init.sh + fi + SCRIPTNAME="cert.sh" + html_head "Certutil Tests" + + ################## Generate noise for our CA cert. ###################### + # NOTE: these keys are only suitable for testing, as this whole thing + # bypasses the entropy gathering. Don't use this method to generate + # keys and certs for product use or deployment. + # + ps -efl > ${NOISE_FILE} 2>&1 + ps aux >> ${NOISE_FILE} 2>&1 + noise + +} + +cert_log() ###################### write the cert_status file +{ + echo "$SCRIPTNAME $*" + echo $* >>${CERT_LOG_FILE} +} + +################################ noise ################################## +# Generate noise for our certs +# +# NOTE: these keys are only suitable for testing, as this whole thing bypasses +# the entropy gathering. Don't use this method to generate keys and certs for +# product use or deployment. +######################################################################### +noise() +{ + #netstat >> ${NOISE_FILE} 2>&1 + date >> ${NOISE_FILE} 2>&1 +} + +################################ certu ################################# +# local shell function to call certutil, also: writes action and options to +# stdout, sets variable RET and writes results to the html file results +######################################################################## +certu() +{ + echo "$SCRIPTNAME: ${CU_ACTION} --------------------------" + + if [ -n "${CU_SUBJECT}" ]; then + #the subject of the cert contains blanks, and the shell + #will strip the quotes off the string, if called otherwise... + echo "certutil -s \"${CU_SUBJECT}\" $*" + certutil -s "${CU_SUBJECT}" $* + RET=$? + CU_SUBJECT="" + else + echo "certutil $*" + certutil $* + RET=$? + fi + if [ "$RET" -ne 0 ]; then + CERTFAILED=$RET + html_failed "<TR><TD>${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "<TR><TD>${CU_ACTION}" + fi + + # echo "Contine?" + # cat > /dev/null + return $RET +} + +############################# cert_init_cert ########################## +# local shell function to initialize creation of client and server certs +######################################################################## +cert_init_cert() +{ + CERTDIR="$1" + CERTNAME="$2" + CERTSERIAL="$3" + DOMAIN="$4" + + if [ ! -d "${CERTDIR}" ]; then + mkdir -p "${CERTDIR}" + else + echo "$SCRIPTNAME: WARNING - ${CERTDIR} exists" + fi + cd "${CERTDIR}" + CERTDIR="." + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${DOMAIN}" + fi + + noise +} + +############################# hw_acc ################################# +# local shell function to add hw accelerator modules to the db +######################################################################## +hw_acc() +{ + HW_ACC_RET=0 + HW_ACC_ERR="" + if [ -n "$O_HWACC" -a "$O_HWACC" = ON -a -z "$USE_64" ] ; then + echo "creating $CERTNAME s cert with hwaccelerator..." + #case $ACCELERATOR in + #rainbow) + + + echo "modutil -add rainbow -libfile /usr/lib/libcryptoki22.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add rainbow -libfile /usr/lib/libcryptoki22.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add rainbow failed in `pwd`" + HW_ACC_RET=1 + HW_ACC_ERR="modutil -add rainbow" + fi + + echo "modutil -add ncipher " + echo " -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add ncipher \ + -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add ncipher failed in `pwd`" + HW_ACC_RET=`expr $HW_ACC_RET + 2` + HW_ACC_ERR="$HW_ACC_ERR,modutil -add ncipher" + fi + if [ "$HW_ACC_RET" -ne 0 ]; then + html_failed "<TR><TD>Adding HW accelerators to certDB for ${CERTNAME} ($HW_ACC_RET) " + else + html_passed "<TR><TD>Adding HW accelerators to certDB for ${CERTNAME}" + fi + + fi + return $HW_ACC_RET +} + +############################# cert_create_cert ######################### +# local shell function to create client certs +# initialize DB, import +# root cert +# add cert to DB +######################################################################## +cert_create_cert() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_cert "$5" + return $? +} + +############################# cert_add_cert ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +######################################################################## +cert_add_cert() +{ + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + return 0 +} + +################################# cert_all_CA ################################ +# local shell function to build the additional Temp. Certificate Authority (CA) +# used for the "real life" ssl test with 2 different CA's in the +# client and in teh server's dir +########################################################################## +cert_all_CA() +{ + echo nss > ${PWFILE} + + ALL_CU_SUBJECT="CN=NSS Test CA, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_CA $CADIR TestCA -x "CTu,CTu,CTu" ${D_CA} "1" + + ALL_CU_SUBJECT="CN=NSS Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" ${D_SERVER_CA} "3" + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" ${D_SERVER_CA} "4" + + + + ALL_CU_SUBJECT="CN=NSS Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" ${D_CLIENT_CA} "6" + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" ${D_CLIENT_CA} "7" + + rm $CLIENT_CADIR/root.cert $SERVER_CADIR/root.cert + # root.cert in $CLIENT_CADIR and in $SERVER_CADIR is the one of the last + # in the chain +} + +################################# cert_CA ################################ +# local shell function to build the Temp. Certificate Authority (CA) +# used for testing purposes, creating a CA Certificate and a root cert +########################################################################## +cert_CA() +{ + CUR_CADIR=$1 + NICKNAME=$2 + SIGNER=$3 + TRUSTARG=$4 + DOMAIN=$5 + CERTSERIAL=$6 + + echo "$SCRIPTNAME: Creating a CA Certificate $NICKNAME ==========================" + + if [ ! -d "${CUR_CADIR}" ]; then + mkdir -p "${CUR_CADIR}" + fi + cd ${CUR_CADIR} + pwd + + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi + + if [ "$SIGNER" = "-x" ] ; then # self signed -> create DB + CU_ACTION="Creating CA Cert DB" + certu -N -d ${LPROFILE} -f ${R_PWFILE} 2>&1 + if [ "$RET" -ne 0 ]; then + Exit 5 "Fatal - failed to create CA $NICKNAME " + fi + echo "$SCRIPTNAME: Certificate initialized ----------" + fi + + + ################# Creating CA Cert ###################################### + # + CU_ACTION="Creating CA Cert $NICKNAME " + CU_SUBJECT=$ALL_CU_SUBJECT + certu -S -n $NICKNAME -t $TRUSTARG -v 600 $SIGNER -d ${LPROFILE} -1 -2 -5 \ + -f ${R_PWFILE} -z ${R_NOISE_FILE} -m $CERTSERIAL 2>&1 <<CERTSCRIPT +5 +9 +n +y +-1 +n +5 +6 +7 +9 +n +CERTSCRIPT + + if [ "$RET" -ne 0 ]; then + echo "return value is $RET" + Exit 6 "Fatal - failed to create CA cert" + fi + + ################# Exporting Root Cert ################################### + # + CU_ACTION="Exporting Root Cert" + certu -L -n $NICKNAME -r -d ${LPROFILE} -o root.cert + if [ "$RET" -ne 0 ]; then + Exit 7 "Fatal - failed to export root cert" + fi + cp root.cert ${NICKNAME}.ca.cert +} + +############################## cert_smime_client ############################# +# local shell function to create client Certificates for S/MIME tests +############################################################################## +cert_smime_client() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ==============" + + cert_create_cert ${ALICEDIR} "Alice" 30 ${D_ALICE} + cert_create_cert ${BOBDIR} "Bob" 40 ${D_BOB} + + echo "$SCRIPTNAME: Creating Dave's Certificate -------------------------" + cert_create_cert "${DAVEDIR}" Dave 50 ${D_DAVE} + + echo "$SCRIPTNAME: Creating multiEmail's Certificate --------------------" + cert_create_cert "${EVEDIR}" "Eve" 60 ${D_EVE} "-7 eve@bogus.net,eve@bogus.cc,beve@bogus.com" + + #echo "************* Copying CA files to ${SERVERDIR}" + #cp ${CADIR}/*.db . + #hw_acc + + ######################################################################### + # + #cd ${CERTDIR} + #CU_ACTION="Creating ${CERTNAME}'s Server Cert" + #CU_SUBJECT="CN=${CERTNAME}, E=${CERTNAME}@bogus.com, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" + #certu -S -n "${CERTNAME}" -c "TestCA" -t "u,u,u" -m "$CERTSERIAL" \ + # -d ${PROFILEDIR} -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + #CU_ACTION="Export Dave's Cert" + #cd ${DAVEDIR} + #certu -L -n "Dave" -r -d ${P_R_DAVE} -o Dave.cert + + ################# Importing Certificates for S/MIME tests ############### + # + echo "$SCRIPTNAME: Importing Certificates ==============================" + CU_ACTION="Import Alices's cert into Bob's db" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_ALICEDIR}/Alice.cert 2>&1 + + CU_ACTION="Import Bob's cert into Alice's db" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_BOBDIR}/Bob.cert 2>&1 + + CU_ACTION="Import Dave's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Dave's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Eve's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + CU_ACTION="Import Eve's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SMIME failed $RET" + else + cert_log "SUCCESS: SMIME passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for extended SSL test +######################################################################## +cert_extended_ssl() +{ + ################# Creating Certs for extended SSL test #################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Certificates, issued by the last ===============" + echo " of a chain of CA's which are not in the same database============" + + echo "Server Cert" + cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 ${D_EXT_SERVER} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + + CU_ACTION="Import Client Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 + echo "Importing all the server's own CA chain into the servers DB" + for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "serverCA" ] ; then + T="-t C,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.) " + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done +#============ + echo "Client Cert" + cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 ${D_EXT_CLIENT} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + CU_ACTION="Import Server Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA.ca.cert" 2>&1 + echo "Importing all the client's own CA chain into the servers DB" + for CA in `find ${CLIENT_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "clientCA" ] ; then + T="-t T,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.)" + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: EXT failed $RET" + else + cert_log "SUCCESS: EXT passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for SSL test +######################################################################## +cert_ssl() +{ + ################# Creating Certs for SSL test ########################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + cert_create_cert ${CLIENTDIR} "TestUser" 70 ${D_CLIENT} + + echo "$SCRIPTNAME: Creating Server CA Issued Certificate for \\" + echo " ${HOSTADDR} ------------------------------------" + cert_create_cert ${SERVERDIR} "${HOSTADDR}" 100 ${D_SERVER} + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} +# cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} +# echo "************* Copying CA files to ${SERVERDIR}" +# cp ${CADIR}/*.db . +# hw_acc +# CU_ACTION="Creating ${CERTNAME}'s Server Cert" +# CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" +# certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d ${PROFILEDIR} \ +# -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SSL failed $RET" + else + cert_log "SUCCESS: SSL passed" + fi +} +############################## cert_stresscerts ################################ +# local shell function to create client certs for SSL stresstest +######################################################################## +cert_stresscerts() +{ + + ############### Creating Certs for SSL stress test ####################### + # + CERTDIR="$CLIENTDIR" + cd "${CERTDIR}" + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${D_CLIENT}" + fi + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + + CONTINUE=$GLOB_MAX_CERT + CERTSERIAL=10 + + while [ $CONTINUE -ge $GLOB_MIN_CERT ] + do + CERTNAME="TestUser$CONTINUE" +# cert_add_cert ${CLIENTDIR} "TestUser$CONTINUE" $CERTSERIAL + cert_add_cert + CERTSERIAL=`expr $CERTSERIAL + 1 ` + CONTINUE=`expr $CONTINUE - 1 ` + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: StressCert failed $RET" + else + cert_log "SUCCESS: StressCert passed" + fi +} + +############################## cert_fips ##################################### +# local shell function to create certificates for FIPS tests +############################################################################## +cert_fips() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating FIPS 140-1 DSA Certificates ==============" + cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 "${D_FIPS}" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" 2>&1 + + echo "$SCRIPTNAME: Enable FIPS mode on database -----------------------" + CU_ACTION="Enable FIPS mode on database for ${CERTNAME}" + echo "modutil -dbdir ${PROFILEDIR} -fips true " + modutil -dbdir ${PROFILEDIR} -fips true 2>&1 <<MODSCRIPT +y +MODSCRIPT + RET=$? + if [ "$RET" -ne 0 ]; then + html_failed "<TR><TD>${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "<TR><TD>${CU_ACTION}" + fi + + CU_ACTION="Generate Certificate for ${CERTNAME}" + CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140-1, L=Mountain View, ST=California, C=US" + certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -v 600 -m 500 -z "${R_NOISE_FILE}" 2>&1 + if [ "$RET" -eq 0 ]; then + cert_log "SUCCESS: FIPS passed" + fi +} + +############################## cert_cleanup ############################ +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +cert_cleanup() +{ + cert_log "$SCRIPTNAME: finished $SCRIPTNAME" + html "</TABLE><BR>" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +cert_init +cert_all_CA +cert_extended_ssl +cert_ssl +cert_smime_client +cert_fips +if [ -n "$DO_DIST_ST" -a "$DO_DIST_ST" = "TRUE" ] ; then + cert_stresscerts + #following lines to be used when databases are to be reused + #cp -r /u/sonmi/tmp/stress/kentuckyderby.13/* $HOSTDIR + #cp -r $HOSTDIR/../${HOST}.2/* $HOSTDIR + +fi +cert_cleanup diff --git a/security/nss/tests/fixtests.sh b/security/nss/tests/fixtests.sh new file mode 100755 index 000000000..e5e90e192 --- /dev/null +++ b/security/nss/tests/fixtests.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# +# 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 test suite. +# +# 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): +# Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. + +####################### fix_test_scripts ####################### +# +# Depending on the argument either enable or disable EC based +# tests in the cert and ssl directories. +# +################################################################ +fix_test_scripts() +{ + FLAG=$1 + CERT_DIR=cert + CERT_SCRIPT=cert.sh + SSL_DIR=ssl + SSLAUTH=sslauth.txt + SSLCOV=sslcov.txt + SSL_SCRIPT=ssl.sh + SSLSTRESS=sslstress.txt + TOOLS_DIR=tools + TOOLS_SCRIPT=tools.sh + EC_PREFIX=ec + NOEC_PREFIX=noec + + if [ xx$FLAG = xx"enable_ecc" ]; then + if [ -f $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLAUTH -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLCOV -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLSTRESS -a \ + -f $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT ]; then + echo "noecc files exist" + else + echo "noecc files are missing" + echo "Saving files as noec" + cp $CERT_DIR/$CERT_SCRIPT $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT + cp $SSL_DIR/$SSLAUTH $SSL_DIR/$NOEC_PREFIX$SSLAUTH + cp $SSL_DIR/$SSLCOV $SSL_DIR/$NOEC_PREFIX$SSLCOV + cp $SSL_DIR/$SSL_SCRIPT $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT + cp $SSL_DIR/$SSLSTRESS $SSL_DIR/$NOEC_PREFIX$SSLSTRESS + cp $TOOLS_DIR/$TOOLS_SCRIPT $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT + fi + echo "Overwriting with ec versions" + cp $CERT_DIR/$EC_PREFIX$CERT_SCRIPT $CERT_DIR/$CERT_SCRIPT + cp $SSL_DIR/$EC_PREFIX$SSLAUTH $SSL_DIR/$SSLAUTH + cp $SSL_DIR/$EC_PREFIX$SSLCOV $SSL_DIR/$SSLCOV + cp $SSL_DIR/$EC_PREFIX$SSL_SCRIPT $SSL_DIR/$SSL_SCRIPT + cp $SSL_DIR/$EC_PREFIX$SSLSTRESS $SSL_DIR/$SSLSTRESS + cp $TOOLS_DIR/$EC_PREFIX$TOOLS_SCRIPT $TOOLS_DIR/$TOOLS_SCRIPT + elif [ xx$FLAG = xx"disable_ecc" ]; then + if [ -f $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLAUTH -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLCOV -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLSTRESS -a \ + -f $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT ]; then + echo "noecc files exist" + echo "Overwriting with noec versions" + cp $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT $CERT_DIR/$CERT_SCRIPT + cp $SSL_DIR/$NOEC_PREFIX$SSLAUTH $SSL_DIR/$SSLAUTH + cp $SSL_DIR/$NOEC_PREFIX$SSLCOV $SSL_DIR/$SSLCOV + cp $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT $SSL_DIR/$SSL_SCRIPT + cp $SSL_DIR/$NOEC_PREFIX$SSLSTRESS $SSL_DIR/$SSLSTRESS + cp $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT $TOOLS_DIR/$TOOLS_SCRIPT + else + echo "Already disabled." + fi + else + echo "Needs either \"enable_ecc\" or \"disable_ecc\" as argument." + fi +} + + +fix_test_scripts $1 diff --git a/security/nss/tests/ssl/ecssl.sh b/security/nss/tests/ssl/ecssl.sh new file mode 100644 index 000000000..512ed3fbb --- /dev/null +++ b/security/nss/tests/ssl/ecssl.sh @@ -0,0 +1,349 @@ +#! /bin/sh +# +# 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. +# +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# +######################################################################## +# +# mozilla/security/nss/tests/ssl/ssl.sh +# +# Script to test NSS SSL +# +# needs to work on all Unix and Windows platforms +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +######################################################################## + +############################## ssl_init ################################ +# local shell function to initialize this script +######################################################################## +ssl_init() +{ + SCRIPTNAME=ssl.sh # sourced - $0 would point to all.sh + + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + + if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then + cd ../common + . ./init.sh + fi + if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here + cd ../cert + . ./cert.sh + fi + SCRIPTNAME=ssl.sh + echo "$SCRIPTNAME: SSL tests ===============================" + + grep "SUCCESS: SSL passed" $CERT_LOG_FILE >/dev/null || { + html_head "SSL Test failure" + Exit 8 "Fatal - SSL of cert.sh needs to pass first" + } + + PORT=${PORT-8443} + + # Test case files + SSLCOV=${QADIR}/ssl/sslcov.txt + SSLAUTH=${QADIR}/ssl/sslauth.txt + SSLSTRESS=${QADIR}/ssl/sslstress.txt + REQUEST_FILE=${QADIR}/ssl/sslreq.txt + + #temparary files + SERVEROUTFILE=${TMP}/tests_server.$$ + SERVERPID=${TMP}/tests_pid.$$ + + R_SERVERPID=../tests_pid.$$ + + TEMPFILES="$TMPFILES ${SERVEROUTFILE} ${SERVERPID}" + + fileout=0 #FIXME, looks like all.sh tried to turn this on but actually didn't + #fileout=1 + #verbose="-v" #FIXME - see where this is usefull + + USER_NICKNAME=TestUser + NORM_EXT="" + + cd ${CLIENTDIR} +} + +########################### is_selfserv_alive ########################## +# local shell function to exit with a fatal error if selfserver is not +# running +######################################################################## +is_selfserv_alive() +{ + if [ ! -f "${SERVERPID}" ]; then + echo "$SCRIPTNAME: Error - selfserv PID file ${SERVERPID} doesn't exist" + sleep 5 + if [ ! -f "${SERVERPID}" ]; then + Exit 9 "Fatal - selfserv pid file ${SERVERPID} does not exist" + fi + fi + PID=`cat ${SERVERPID}` + #if [ "${OS_ARCH}" = "Linux" ]; then + kill -0 $PID >/dev/null 2>/dev/null || Exit 10 "Fatal - selfserv process not detectable" + #else + #$PS -e | grep $PID >/dev/null || \ + #Exit 10 "Fatal - selfserv process not detectable" + #fi +} + +########################### wait_for_selfserv ########################## +# local shell function to wait until selfserver is running and initialized +######################################################################## +wait_for_selfserv() +{ + echo "tstclnt -p ${PORT} -h ${HOST} -q " + echo " -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \\" + #echo "tstclnt -q started at `date`" + tstclnt -p ${PORT} -h ${HOST} -q -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} + if [ $? -ne 0 ]; then + html_failed "<TR><TD> Wait for Server " + echo "RETRY: tstclnt -p ${PORT} -h ${HOST} -q \\" + echo " -d ${P_R_CLIENTDIR} < ${REQUEST_FILE}" + tstclnt -p ${PORT} -h ${HOST} -q -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} + elif [ sparam = "-c ABCDEFGHIJKLMNOPQRSTabcdefghijklmnvy" ] ; then # "$1" = "cov" ] ; then + html_passed "<TR><TD> Wait for Server" + fi + is_selfserv_alive +} + +########################### kill_selfserv ############################## +# local shell function to kill the selfserver after the tests are done +######################################################################## +kill_selfserv() +{ + ${KILL} `cat ${SERVERPID}` + wait `cat ${SERVERPID}` + if [ ${fileout} -eq 1 ]; then + cat ${SERVEROUTFILE} + fi + # On Linux selfserv needs up to 30 seconds to fully die and free + # the port. Wait until the port is free. (Bug 129701) + if [ "${OS_ARCH}" = "Linux" ]; then + until selfserv -b -p ${PORT} 2>/dev/null; do + sleep 1 + done + fi + rm ${SERVERPID} +} + +########################### start_selfserv ############################# +# local shell function to start the selfserver with the parameters required +# for this test and log information (parameters, start time) +# also: wait until the server is up and running +######################################################################## +start_selfserv() +{ + if [ -n "$testname" ] ; then + echo "$SCRIPTNAME: $testname ----" + fi + sparam=`echo $sparam | sed -e 's;_; ;g'` + echo "selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \\" + echo " -e ${HOSTADDR}-ec \\" + echo " -w nss ${sparam} -i ${R_SERVERPID} $verbose &" + echo "selfserv started at `date`" + if [ ${fileout} -eq 1 ]; then + selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \ + -e ${HOSTADDR}-ec \ + -w nss ${sparam} -i ${R_SERVERPID} $verbose \ + > ${SERVEROUTFILE} 2>&1 & + else + selfserv -D -p ${PORT} -d ${P_R_SERVERDIR} -n ${HOSTADDR} \ + -e ${HOSTADDR}-ec \ + -w nss ${sparam} -i ${R_SERVERPID} $verbose & + fi + wait_for_selfserv +} + +############################## ssl_cov ################################# +# local shell function to perform SSL Cipher Coverage tests +######################################################################## +ssl_cov() +{ + html_head "SSL Cipher Coverage $NORM_EXT" + + testname="" + sparam="-c ABCDEFGHIJKLMNOPQRSTabcdefghijklmnvyz" + start_selfserv # Launch the server + + p="" + + while read tls param testname + do + p=`echo "$testname" | sed -e "s/ .*//"` #sonmi, only run extended test on SSL3 and TLS + + if [ "$p" = "SSL2" -a "$NORM_EXT" = "Extended test" ] ; then + echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" + elif [ "$tls" != "#" ] ; then + echo "$SCRIPTNAME: running $testname ----------------------------" + TLS_FLAG=-T + if [ $tls = "TLS" ]; then + TLS_FLAG="" + fi + + is_selfserv_alive + echo "tstclnt -p ${PORT} -h ${HOST} -c ${param} ${TLS_FLAG} \\" + echo " -f -d ${P_R_CLIENTDIR} < ${REQUEST_FILE}" + + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + tstclnt -p ${PORT} -h ${HOST} -c ${param} ${TLS_FLAG} -f \ + -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? + cat ${TMP}/$HOST.tmp.$$ + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + html_msg $ret 0 "${testname}" + fi + done < ${SSLCOV} + + kill_selfserv + html "</TABLE><BR>" +} + +############################## ssl_auth ################################ +# local shell function to perform SSL Client Authentication tests +######################################################################## +ssl_auth() +{ + html_head "SSL Client Authentication $NORM_EXT" + + while read value sparam cparam testname + do + if [ $value != "#" ]; then + cparam=`echo $cparam | sed -e 's;_; ;g' -e "s/TestUser/$USER_NICKNAME/g" ` + start_selfserv + + echo "tstclnt -p ${PORT} -h ${HOST} -f -d ${P_R_CLIENTDIR} \\" + echo " ${cparam} < ${REQUEST_FILE}" + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + tstclnt -p ${PORT} -h ${HOST} -f ${cparam} \ + -d ${P_R_CLIENTDIR} < ${REQUEST_FILE} \ + >${TMP}/$HOST.tmp.$$ 2>&1 + ret=$? + cat ${TMP}/$HOST.tmp.$$ + rm ${TMP}/$HOST.tmp.$$ 2>/dev/null + + html_msg $ret $value "${testname}" \ + "produced a returncode of $ret, expected is $value" + kill_selfserv + fi + done < ${SSLAUTH} + + html "</TABLE><BR>" +} + + +############################## ssl_stress ############################## +# local shell function to perform SSL stress test +######################################################################## +ssl_stress() +{ + html_head "SSL Stress Test $NORM_EXT" + + while read value sparam cparam testname + do + p=`echo "$testname" | sed -e "s/Stress //" -e "s/ .*//"` #sonmi, only run extended test on SSL3 and TLS + if [ "$p" = "SSL2" -a "$NORM_EXT" = "Extended test" ] ; then + echo "$SCRIPTNAME: skipping $testname for $NORM_EXT" + elif [ $value != "#" ]; then + cparam=`echo $cparam | sed -e 's;_; ;g'` + start_selfserv + if [ `uname -n` = "sjsu" ] ; then + echo "debugging disapering selfserv... ps -ef | grep selfserv" + ps -ef | grep selfserv + fi + + echo "strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} -w nss $cparam \\" + echo " $verbose ${HOSTADDR}" + echo "strsclnt started at `date`" + strsclnt -q -p ${PORT} -d ${P_R_CLIENTDIR} -w nss $cparam \ + $verbose ${HOSTADDR} + ret=$? + echo "strsclnt completed at `date`" + html_msg $ret $value "${testname}" + if [ `uname -n` = "sjsu" ] ; then + echo "debugging disapering selfserv... ps -ef | grep selfserv" + ps -ef | grep selfserv + fi + kill_selfserv + fi + done < ${SSLSTRESS} + + html "</TABLE><BR>" +} + + +############################## ssl_cleanup ############################# +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +ssl_cleanup() +{ + rm $SERVERPID 2>/dev/null + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +#this script may be sourced from the distributed stress test - in this case do nothing... + +if [ -z "$DO_REM_ST" -a -z "$DO_DIST_ST" ] ; then + ssl_init + ssl_cov + ssl_auth + ssl_stress + + SERVERDIR=$EXT_SERVERDIR + CLIENTDIR=$EXT_CLIENTDIR + R_SERVERDIR=$R_EXT_SERVERDIR + R_CLIENTDIR=$R_EXT_CLIENTDIR + P_R_SERVERDIR=$P_R_EXT_SERVERDIR + P_R_CLIENTDIR=$P_R_EXT_CLIENTDIR + USER_NICKNAME=ExtendedSSLUser + NORM_EXT="Extended test" + cd ${CLIENTDIR} + ssl_cov + ssl_auth + ssl_stress + ssl_cleanup +fi diff --git a/security/nss/tests/ssl/ecsslauth.txt b/security/nss/tests/ssl/ecsslauth.txt new file mode 100644 index 000000000..e7204feb2 --- /dev/null +++ b/security/nss/tests/ssl/ecsslauth.txt @@ -0,0 +1,50 @@ +# +# This file defines the tests for client auth. +# +# expected +# return server client Test Case name +# value params params +# ------ ------ ------ --------------- + 0 -r -w_nss TLS Request don't require client auth (client does not provide auth) + 0 -r -w_bogus_-n_TestUser TLS Request don't require client auth (bad password) + 0 -r -w_nss_-n_TestUser TLS Request don't require client auth (client auth) + 0 -r_-r -w_nss TLS Require client auth (client does not provide auth) + 254 -r_-r -w_bogus_-n_TestUser TLS Require client auth (bad password) + 0 -r_-r -w_nss_-n_TestUser_ TLS Require client auth (client auth) + 0 -r -T_-w_nss SSL3 Request don't require client auth (client does not provide auth) + 0 -r -T_-n_TestUser_-w_bogus SSL3 Request don't require client auth (bad password) + 0 -r -T_-n_TestUser_-w_nss SSL3 Request don't require client auth (client auth) + 0 -r_-r -T_-w_nss SSL3 Require client auth (client does not provide auth) + 254 -r_-r -T_-n_TestUser_-w_bogus SSL3 Require client auth (bad password) + 0 -r_-r -T_-n_TestUser_-w_nss SSL3 Require client auth (client auth) + 0 -r_-r_-r -w_nss TLS Request don't require client auth on 2nd hs (client does not provide auth) + 0 -r_-r_-r -w_bogus_-n_TestUser TLS Request don't require client auth on 2nd hs (bad password) + 0 -r_-r_-r -w_nss_-n_TestUser TLS Request don't require client auth on 2nd hs (client auth) + 0 -r_-r_-r_-r -w_nss TLS Require client auth on 2nd hs (client does not provide auth) + 1 -r_-r_-r_-r -w_bogus_-n_TestUser TLS Require client auth on 2nd hs (bad password) + 0 -r_-r_-r_-r -w_nss_-n_TestUser_ TLS Require client auth on 2nd hs (client auth) + 0 -r_-r_-r -T_-w_nss SSL3 Request don't require client auth on 2nd hs (client does not provide auth) + 0 -r_-r_-r -T_-n_TestUser_-w_bogus SSL3 Request don't require client auth on 2nd hs (bad password) + 0 -r_-r_-r -T_-n_TestUser_-w_nss SSL3 Request don't require client auth on 2nd hs (client auth) + 0 -r_-r_-r_-r -T_-w_nss SSL3 Require client auth on 2nd hs (client does not provide auth) + 1 -r_-r_-r_-r -T_-n_TestUser_-w_bogus SSL3 Require client auth on 2nd hs (bad password) + 0 -r_-r_-r_-r -T_-n_TestUser_-w_nss SSL3 Require client auth on 2nd hs (client auth) +# +# Use EC cert for client authentication +# + 0 -r -w_bogus_-n_TestUser-ec TLS Request don't require client auth (EC) (bad password) + 0 -r -w_nss_-n_TestUser-ec TLS Request don't require client auth (EC) (client auth) + 254 -r_-r -w_bogus_-n_TestUser-ec TLS Require client auth (EC) (bad password) + 0 -r_-r -w_nss_-n_TestUser-ec_ TLS Require client auth (EC) (client auth) + 0 -r -T_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth (EC) (bad password) + 0 -r -T_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth (EC) (client auth) + 254 -r_-r -T_-n_TestUser-ec_-w_bogus SSL3 Require client auth (EC) (bad password) + 0 -r_-r -T_-n_TestUser-ec_-w_nss SSL3 Require client auth (EC) (client auth) + 0 -r_-r_-r -w_bogus_-n_TestUser-ec TLS Request don't require client auth on 2nd hs (EC) (bad password) + 0 -r_-r_-r -w_nss_-n_TestUser-ec TLS Request don't require client auth on 2nd hs (EC) (client auth) + 1 -r_-r_-r_-r -w_bogus_-n_TestUser-ec TLS Require client auth on 2nd hs (EC) (bad password) + 0 -r_-r_-r_-r -w_nss_-n_TestUser-ec_ TLS Require client auth on 2nd hs (EC) (client auth) + 0 -r_-r_-r -T_-n_TestUser-ec_-w_bogus SSL3 Request don't require client auth on 2nd hs (EC) (bad password) + 0 -r_-r_-r -T_-n_TestUser-ec_-w_nss SSL3 Request don't require client auth on 2nd hs (EC) (client auth) + 1 -r_-r_-r_-r -T_-n_TestUser-ec_-w_bogus SSL3 Require client auth on 2nd hs (EC) (bad password) + 0 -r_-r_-r_-r -T_-n_TestUser-ec_-w_nss SSL3 Require client auth on 2nd hs (EC) (client auth) diff --git a/security/nss/tests/ssl/ecsslcov.txt b/security/nss/tests/ssl/ecsslcov.txt new file mode 100644 index 000000000..f01e56899 --- /dev/null +++ b/security/nss/tests/ssl/ecsslcov.txt @@ -0,0 +1,83 @@ +# +# This file enables test coverage of the various SSL ciphers +# +# NOTE: SSL2 ciphers are independent of whether TLS is enabled or not. We +# mix up the enable functions so we can tests boths paths. +# +# Enable Cipher Test Name +# TLS +# + noTLS A SSL2 RC4 128 WITH MD5 + TLS B SSL2 RC4 128 EXPORT40 WITH MD5 + TLS C SSL2 RC2 128 CBC WITH MD5 + noTLS D SSL2 RC2 128 CBC EXPORT40 WITH MD5 + TLS E SSL2 DES 64 CBC WITH MD5 + noTLS F SSL2 DES 192 EDE3 CBC WITH MD5 +# +# ECC ciphers (SSL3) +# + noTLS G SSL3 ECDH ECDSA WITH NULL SHA + noTLS H SSL3 ECDH ECDSA WITH RC4 128 SHA + noTLS I SSL3 ECDH ECDSA WITH DES CBC SHA + noTLS J SSL3 ECDH ECDSA WITH 3DES EDE CBC SHA + noTLS K SSL3 ECDH ECDSA WITH AES 128 CBC SHA + noTLS L SSL3 ECDH ECDSA WITH AES 256 CBC SHA + noTLS M SSL3 ECDH RSA WITH NULL SHA + noTLS N SSL3 ECDH RSA WITH RC4 128 SHA + noTLS O SSL3 ECDH RSA WITH DES CBC SHA + noTLS P SSL3 ECDH RSA WITH 3DES EDE CBC SHA + noTLS Q SSL3 ECDH RSA WITH AES 128 CBC SHA + noTLS R SSL3 ECDH RSA WITH AES 256 CBC SHA + noTLS S SSL3 ECDHE ECDSA WITH AES 128 CBC SHA + noTLS T SSL3 ECDHE RSA WITH AES 128 CBC SHA +# +# ECC ciphers (TLS) +# + TLS G TLS ECDH ECDSA WITH NULL SHA + TLS H TLS ECDH ECDSA WITH RC4 128 SHA + TLS I TLS ECDH ECDSA WITH DES CBC SHA + TLS J TLS ECDH ECDSA WITH 3DES EDE CBC SHA + TLS K TLS ECDH ECDSA WITH AES 128 CBC SHA + TLS L TLS ECDH ECDSA WITH AES 256 CBC SHA + TLS M TLS ECDH RSA WITH NULL SHA + TLS N TLS ECDH RSA WITH RC4 128 SHA + TLS O TLS ECDH RSA WITH DES CBC SHA + TLS P TLS ECDH RSA WITH 3DES EDE CBC SHA + TLS Q TLS ECDH RSA WITH AES 128 CBC SHA + TLS R TLS ECDH RSA WITH AES 256 CBC SHA + TLS S TLS ECDHE ECDSA WITH AES 128 CBC SHA + TLS T TLS ECDHE RSA WITH AES 128 CBC SHA +# +# +# noTLS a SSL3 FORTEZZA DMS WITH FORTEZZA CBC SHA +# noTLS b SSL3 FORTEZZA DMS WITH RC4 128 SHA + noTLS c SSL3 RSA WITH RC4 128 MD5 + noTLS d SSL3 RSA WITH 3DES EDE CBC SHA + noTLS e SSL3 RSA WITH DES CBC SHA + noTLS f SSL3 RSA EXPORT WITH RC4 40 MD5 + noTLS g SSL3 RSA EXPORT WITH RC2 CBC 40 MD5 +# noTLS h SSL3 FORTEZZA DMS WITH NULL SHA + noTLS i SSL3 RSA WITH NULL MD5 + noTLS j SSL3 RSA FIPS WITH 3DES EDE CBC SHA + noTLS k SSL3 RSA FIPS WITH DES CBC SHA + noTLS l SSL3 RSA EXPORT WITH DES CBC SHA (new) + noTLS m SSL3 RSA EXPORT WITH RC4 56 SHA (new) + noTLS n SSL3 RSA WITH RC4 128 SHA + noTLS v SSL3 RSA WITH AES 128 CBC SHA + noTLS y SSL3 RSA WITH AES 256 CBC SHA + noTLS z SSL3 RSA WITH NULL SHA +# + TLS c TLS RSA WITH RC4 128 MD5 + TLS d TLS RSA WITH 3DES EDE CBC SHA + TLS e TLS RSA WITH DES CBC SHA + TLS f TLS RSA EXPORT WITH RC4 40 MD5 + TLS g TLS RSA EXPORT WITH RC2 CBC 40 MD5 + TLS i TLS RSA WITH NULL MD5 + TLS j TLS RSA FIPS WITH 3DES EDE CBC SHA + TLS k TLS RSA FIPS WITH DES CBC SHA + TLS l TLS RSA EXPORT WITH DES CBC SHA (new) + TLS m TLS RSA EXPORT WITH RC4 56 SHA (new) + TLS n TLS RSA WITH RC4 128 SHA + TLS v TLS RSA WITH AES 128 CBC SHA + TLS y TLS RSA WITH AES 256 CBC SHA + TLS z TLS RSA WITH NULL SHA diff --git a/security/nss/tests/ssl/ecsslstress.txt b/security/nss/tests/ssl/ecsslstress.txt new file mode 100644 index 000000000..f9feb5d99 --- /dev/null +++ b/security/nss/tests/ssl/ecsslstress.txt @@ -0,0 +1,24 @@ +# +# This file defines the tests for client auth. +# +# expected +# return server client Test Case name +# value params params +# ------ ------ ------ --------------- + 0 _ -c_1000_-C_A Stress SSL2 RC4 128 with MD5 + 0 _ -c_1000_-C_c Stress SSL3 RC4 128 with MD5 + 0 _ -c_1000_-C_c Stress TLS RC4 128 with MD5 +# +# ECC ciphers +# XXX Session reuse does not seem to work for ECDH-ECDSA, ECDHE-ECDSA ciphers +# but works ok for ECDHE-RSA ciphers. With session reuse turned off +# setting up 1000 connections would take too long so use only 10 connections +# + 0 -c_H -c_10_-C_H_-N Stress TLS ECDH-ECDSA RC4 128 with SHA (no reuse) + 0 -c_S -c_10_-C_S_-N Stress TLS ECDHE-ECDSA AES 128 CBC with SHA (no reuse) + 0 -c_T -c_1000_-C_T Stress TLS ECDHE-RSA AES 128 CBC with SHA + +# +# add client auth versions here... +# +# 0 -r -w_bogus_-n_"Test_User" TLS Request don't require client auth (bad password) diff --git a/security/nss/tests/ssl/sslreq.dat b/security/nss/tests/ssl/sslreq.dat new file mode 100644 index 000000000..2f7ad7736 --- /dev/null +++ b/security/nss/tests/ssl/sslreq.dat @@ -0,0 +1,2 @@ +GET / HTTP/1.0
+
diff --git a/security/nss/tests/tools/ectools.sh b/security/nss/tests/tools/ectools.sh new file mode 100644 index 000000000..d3ce81fa4 --- /dev/null +++ b/security/nss/tests/tools/ectools.sh @@ -0,0 +1,210 @@ +#! /bin/sh +# +# 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. +# +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# +######################################################################## +# +# mozilla/security/nss/tests/tools/tools.sh +# +# Script to test basic functionallity of NSS tools +# +# needs to work on all Unix and Windows platforms +# +# tests implemented: +# pk12util +# signtool +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +######################################################################## + +############################## tools_init ############################## +# local shell function to initialize this script +######################################################################## +tools_init() +{ + SCRIPTNAME=tools.sh # sourced - $0 would point to all.sh + + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + + if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then + cd ../common + . ./init.sh + fi + if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here + cd ../cert + . ./cert.sh + fi + SCRIPTNAME=tools.sh + html_head "Tools Tests" + + grep "SUCCESS: SMIME passed" $CERT_LOG_FILE >/dev/null || { + Exit 15 "Fatal - S/MIME of cert.sh needs to pass first" + } + + TOOLSDIR=${HOSTDIR}/tools + COPYDIR=${TOOLSDIR}/copydir + + R_TOOLSDIR=../tools + R_COPYDIR=../tools/copydir + P_R_COPYDIR=${R_COPYDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_COPYDIR="multiaccess:Tools.$version" + fi + + mkdir -p ${TOOLSDIR} + mkdir -p ${COPYDIR} + mkdir -p ${TOOLSDIR}/html + cp ${QADIR}/tools/sign*.html ${TOOLSDIR}/html + + cd ${TOOLSDIR} +} + +############################## tools_p12 ############################### +# local shell function to test basic functionality of pk12util +######################################################################## +tools_p12() +{ + echo "$SCRIPTNAME: Exporting Alice's email cert & key------------------" + echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email cert & key -----------------" + echo "pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)" + check_tmpfile + + echo "$SCRIPTNAME: Exporting Alice's email EC cert & key---------------" + echo "pk12util -o Alice-ec.p12 -n \"Alice-ec\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice-ec.p12 -n "Alice-ec" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email EC cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email EC cert & key --------------" + echo "pk12util -i Alice-ec.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice-ec.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email EC cert & key (pk12util -i)" + check_tmpfile + +} + +############################## tools_sign ############################## +# local shell function pk12util uses a hardcoded tmp file, if this exists +# and is owned by another user we don't get reasonable errormessages +######################################################################## +check_tmpfile() +{ + if [ $ret != "0" -a -f /tmp/Pk12uTemp ] ; then + echo "Error: pk12util temp file exists. Please remove this file and" + echo " rerun the test (/tmp/Pk12uTemp) " + fi +} + +############################## tools_sign ############################## +# local shell function to test basic functionality of signtool +######################################################################## +tools_sign() +{ + echo "$SCRIPTNAME: Create objsign cert -------------------------------" + echo "signtool -G \"objectsigner\" -d ${P_R_ALICEDIR} -p \"nss\"" + signtool -G "objsigner" -d ${P_R_ALICEDIR} -p "nss" 2>&1 <<SIGNSCRIPT +y +TEST +MOZ +NSS +NY +US +liz +liz@moz.org +SIGNSCRIPT + html_msg $? 0 "Create objsign cert (signtool -G)" + + echo "$SCRIPTNAME: Signing a set of files ----------------------------" + echo "signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p \"nss\" -k objsigner \\" + echo " ${R_TOOLSDIR}/html" + signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p "nss" -k objsigner \ + ${R_TOOLSDIR}/html + html_msg $? 0 "Signing a set of files (signtool -Z)" + + echo "$SCRIPTNAME: Listing signed files in jar ----------------------" + echo "signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner" + signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner + html_msg $? 0 "Listing signed files in jar (signtool -v)" + + echo "$SCRIPTNAME: Show who signed jar ------------------------------" + echo "signtool -w nojs.jar -d ${P_R_ALICEDIR}" + signtool -w nojs.jar -d ${P_R_ALICEDIR} + html_msg $? 0 "Show who signed jar (signtool -w)" +} + +############################## tools_cleanup ########################### +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +tools_cleanup() +{ + html "</TABLE><BR>" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +tools_init + +tools_p12 + +tools_sign +tools_cleanup + + diff --git a/security/nss/tests/tools/noectools.sh b/security/nss/tests/tools/noectools.sh new file mode 100644 index 000000000..b301fc72b --- /dev/null +++ b/security/nss/tests/tools/noectools.sh @@ -0,0 +1,189 @@ +#! /bin/sh +# +# 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 the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# +######################################################################## +# +# mozilla/security/nss/tests/tools/tools.sh +# +# Script to test basic functionallity of NSS tools +# +# needs to work on all Unix and Windows platforms +# +# tests implemented: +# pk12util +# signtool +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +######################################################################## + +############################## tools_init ############################## +# local shell function to initialize this script +######################################################################## +tools_init() +{ + SCRIPTNAME=tools.sh # sourced - $0 would point to all.sh + + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + + if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then + cd ../common + . ./init.sh + fi + if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here + cd ../cert + . ./cert.sh + fi + SCRIPTNAME=tools.sh + html_head "Tools Tests" + + grep "SUCCESS: SMIME passed" $CERT_LOG_FILE >/dev/null || { + Exit 15 "Fatal - S/MIME of cert.sh needs to pass first" + } + + TOOLSDIR=${HOSTDIR}/tools + COPYDIR=${TOOLSDIR}/copydir + + R_TOOLSDIR=../tools + R_COPYDIR=../tools/copydir + P_R_COPYDIR=${R_COPYDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_COPYDIR="multiaccess:Tools.$version" + fi + + mkdir -p ${TOOLSDIR} + mkdir -p ${COPYDIR} + mkdir -p ${TOOLSDIR}/html + cp ${QADIR}/tools/sign*.html ${TOOLSDIR}/html + + cd ${TOOLSDIR} +} + +############################## tools_p12 ############################### +# local shell function to test basic functionality of pk12util +######################################################################## +tools_p12() +{ + echo "$SCRIPTNAME: Exporting Alice's email cert & key------------------" + echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email cert & key -----------------" + echo "pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)" + check_tmpfile +} + +############################## tools_sign ############################## +# local shell function pk12util uses a hardcoded tmp file, if this exists +# and is owned by another user we don't get reasonable errormessages +######################################################################## +check_tmpfile() +{ + if [ $ret != "0" -a -f /tmp/Pk12uTemp ] ; then + echo "Error: pk12util temp file exists. Please remove this file and" + echo " rerun the test (/tmp/Pk12uTemp) " + fi +} + +############################## tools_sign ############################## +# local shell function to test basic functionality of signtool +######################################################################## +tools_sign() +{ + echo "$SCRIPTNAME: Create objsign cert -------------------------------" + echo "signtool -G \"objectsigner\" -d ${P_R_ALICEDIR} -p \"nss\"" + signtool -G "objsigner" -d ${P_R_ALICEDIR} -p "nss" 2>&1 <<SIGNSCRIPT +y +TEST +MOZ +NSS +NY +US +liz +liz@moz.org +SIGNSCRIPT + html_msg $? 0 "Create objsign cert (signtool -G)" + + echo "$SCRIPTNAME: Signing a set of files ----------------------------" + echo "signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p \"nss\" -k objsigner \\" + echo " ${R_TOOLSDIR}/html" + signtool -Z nojs.jar -d ${P_R_ALICEDIR} -p "nss" -k objsigner \ + ${R_TOOLSDIR}/html + html_msg $? 0 "Signing a set of files (signtool -Z)" + + echo "$SCRIPTNAME: Listing signed files in jar ----------------------" + echo "signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner" + signtool -v nojs.jar -d ${P_R_ALICEDIR} -p nss -k objsigner + html_msg $? 0 "Listing signed files in jar (signtool -v)" + + echo "$SCRIPTNAME: Show who signed jar ------------------------------" + echo "signtool -w nojs.jar -d ${P_R_ALICEDIR}" + signtool -w nojs.jar -d ${P_R_ALICEDIR} + html_msg $? 0 "Show who signed jar (signtool -w)" +} + +############################## tools_cleanup ########################### +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +tools_cleanup() +{ + html "</TABLE><BR>" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +tools_init + +tools_p12 + +tools_sign +tools_cleanup + + |